Salut! J'ai besoin d'un peu d'aide... Je débute en haskell. J'essai d'écrire un petit programme qui implémente les "polynômes interpolateurs de Lagrange". Mais ma question est plus générale, c'est que j'ai souvent du mal avec le moteur d'inférence de Haskell. En effet, un coup mon code compile. Ensuite je fait une petite modif sur une ligne et ça ne compile plus en me levant une erreur sur une partie (apparemment) complètement différente du code!! Dans mon exemple j'ai une variable *nombre_points*. C'est clairement un entier. Comment le préciser? Je voudrais aussi l'utiliser dans des divisions. Comment faire? Je pense que c'est le problème dans mon exemple ci-dessous. Merci pour votre aide! Corentin PS: Y as t-il un forum en Français d'entraide? Il me sort une erreur du style: *Lagrange.hs:60:13: No instance for (Fractional Int) arising from use of `us' at Lagrange.hs:60:13-17 Possible fix: add an instance declaration for (Fractional Int) In the second argument of `map', namely `(us (m))' In the expression: map by (us (m)) In the definition of `ys': ys = map by (us (m))* Voici l'exemple: *module Lagrange where nombre_points = 7 -- creation d'une liste exluant i list i = [x | x <- [0..nombre_points-1], x /= i] -- un terme du polynôme de Lagrange un_terme t j i = (t - i)/(j - i) --produit des termes pour obtenir le polynôme d'un point les_termes t j = map (un_terme t j) (list j) poly t j = product (les_termes t j) --Si je décommente les 2 lignes suivantes et que je commente l'autre définition de blend ci-dessous, ça marche: --blend (a,t) = a(0) * (poly t 0) + a(1) * (poly t 1) + a(2) * (poly t 2) + a(3) * (poly t 3) + -- a(4) * (poly t 4) + a(5) * (poly t 5) + a(6) * (poly t 6) --t est le paramètre du polynôme, a sera la coordonnée (x ou y). blend_un_point t a numero_point = a(numero_point) * (poly t numero_point) blend_les_points t a = map (blend_un_point t a) [0..6] blend (a,t) = sum (blend_les_points t a) -- Sample points xy = [(-4.0,0.0), (-1.0,1.0), (-3.0,3.0), (0.0,4.0), (3.0,3.0),(1.0,1.0),( 4.0,0.0)] --creation des fonctions x et y x a = fst (xy !! a) y a = snd (xy !! a) -- Blend the sample points for some given u: bx(u) = blend(x,u) by(u) = blend(y,u) -- Take m+1 values for u, from 0 to nombre_points, equally spaced: us(m) = map (/m) [0.0..(7-1)*m] -- For m = 50.0 -- we get us(m)=[0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]. -- Now get a list of points for the above values of the parameter: xs = map bx (us(m))* * ys = map by (us(m)) -- Running this, we get, where I've rounded the results to 2 digits: -- -- xs = [0.00, 0.38, 0.75, 1.1, 1.5, 1.9, 2.3, 2.6, 3.0] -- ys = [0.00, 0.46, 1.00, 1.7, 2.3, 2.8, 3.1, 3.2, 3.0] -- Finally, get a list of pairs (x,y), i.e. a list of points: ps = zip xs ys -- In this example, running "ps" we get, after rounding, the points: -- -- [(0, 0), (0.38, 0.46), (0.75, 1), (1.1, 1.7), -- (1.5, 2.3), (1.9, 2.8), (2.3, 3.1), (2.6, 3.2), (3, 3)] -- -- Now plot lines joining these points to get an approximation of the curve *
On 9/10/07, Dupont Corentin
Salut! J'ai besoin d'un peu d'aide... Je débute en haskell. J'essai d'écrire un petit programme qui implémente les "polynômes interpolateurs de Lagrange".
Mais ma question est plus générale, c'est que j'ai souvent du mal avec le moteur d'inférence de Haskell. En effet, un coup mon code compile. Ensuite je fait une petite modif sur une ligne et ça ne compile plus en me levant une erreur sur une partie (apparemment) complètement différente du code!!
Ca arrive souvent quand on laisse Haskell deviner tout seul le type des fonctions. Une solution tout simple consiste à renseigner le type des fonctions, de telle qu'haskell signale de suite quand une signature de fonction ne correspond pas avec le code qu'il voit. Sans la signature, haskell détermine un type qui est peut être faut pour la fonction, puis signale l'erreur dans une autre fonction qui fait appel à la première.
Dans mon exemple j'ai une variable nombre_points. C'est clairement un entier. Comment le préciser?
nombre_points :: Int
Salut,
us(m) = map (/m) [0.0..(7-1)*m]
Le (/) ne prend que de types qui sont des instances de la classe Fractional (e.g. Double, Float). Comme tu as utilisé un / m, Haskell a inféré que m est forcement dans cette classe. Donc si dans une autre fonction tu passe un Int à us, il y aura un erreur de typage. Je crois que les fonctions fromIntegral ou realToFrac pourraient servir http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v%3A... Peut-être ça sera une bonne idée de faire us(m) = map (/mf) [0.0..(7-1)*m] where mf = fromInteger m forum ----- Il y a #haskell et #haskell.fr sur irc.freenode.net. La communauté Haskell a plus tendence a utiliser les listes de diffusion ou IRC que les forums (message boards?) ou Usenet. style ----- Je crois que c'est plus courant de faire us m = ... sans les parenthèses dans les paramètres Lorsque mes fonctions sont «externes», c'est à dire, pas cachées dans un 'let' ou un 'where', je préfère exprimer mes intentions explicitement avec une signature de type. Par exemple, us :: Int -> [Float] us m = ... Ou peut-être tu voulais une fonction plus generale us :: (Integral a, Fractional b) => a -> [b] us m = ... C'est pratique pour comprendre les erreurs de typage, et aussi comme source de documentation. -- Eric Kow http://www.loria.fr/~kow PGP Key ID: 08AC04F9 Merci de corriger mon français.
J'ai tranformé mon programme de la manière suivante (voir ci-après). J'ai spécifié le type de la plupart des fonctions. Ca marche mieux, mais l'écriture est sérieusement plus lourde! J'ai encore un problème: courbe = defaultPlotLines { plot_lines_values = [[ (Point a b) | (a,b) <- ps]], plot_lines_style = solidLine lineWidth 0 0 1 } donne l'erreur: Couldn't match expected type `Double' against inferred type `Float' In the first argument of `Point', namely `a' In the expression: (Point a b) In the expression: [(Point a b) | (a, b) <- ps] en effet Point prend des doubles. Je n'ai pas trouvé de fonctions de conversion Float vers Double... Merci! Corentin *module Lagrange where* *nombre_points :: Integer nombre_points = 7* *-- creation d'une liste exluant i list :: Integer -> [Integer] list i = filter (/=i) [0..nombre_points-1] * *-- un terme du polynôme de Lagrange --un_terme :: Float -> Integer -> Integer -> Float un_terme t j i = (t - i_f)/(j_f - i_f) where i_f = fromInteger i j_f = fromInteger j* *--produit des termes pour obtenir le polynôme d'un point les_termes t j = map (un_terme t j) (list j) poly t j = product (les_termes t j)* * * *--blend (a,t) = a(0) * (poly t 0) + a(1) * (poly t 1) + a(2) * (poly t 2) + a(3) * (poly t 3) + -- a(4) * (poly t 4) + a(5) * (poly t 5) + a(6) * (poly t 6)* *--t est le paramètre du polynôme, a sera la coordonnée (x ou y). blend_un_point :: Float -> (Integer -> Float) -> Integer -> Float blend_un_point t a numero_point = a(numero_point) * (poly t numero_point) blend_les_points t a = map (blend_un_point t a) [0..6]* *blend :: (Integer -> Float, Float) -> Float blend (a,t) = sum (blend_les_points t a)* *-- Sample points xy = [(-4.0,0.0), (-1.0,1.0), (-3.0,3.0), (0.0,4.0), (3.0,3.0),(1.0,1.0),( 4.0,0.0)]* *--creation des fonctions x et y x :: Integer -> Float x pos = fst (xy !! pos_Integer) where pos_Integer = fromInteger(pos) y :: Integer -> Float y pos = snd (xy !! pos_Integer) where pos_Integer = fromInteger(pos)* *-- Blend the sample points for some given u: bx :: Float -> Float bx(u) = blend(x,u)* *by :: Float -> Float by(u) = blend(y,u)* *-- Take m+1 values for u, from 0 to nombre_points, equally spaced: us :: Integer -> [Float] us m = map (/mf) [0..6*mf] where mf = fromInteger m* *-- For* *m = 50* *-- we get us(m)=[0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0].* *-- Now get a list of points for the above values of the parameter:* *xs = map bx (us(m)) ys = map by (us(m))* *-- Running this, we get, where I've rounded the results to 2 digits: -- -- xs = [0.00, 0.38, 0.75, 1.1, 1.5, 1.9, 2.3, 2.6, 3.0] -- ys = [0.00, 0.46, 1.00, 1.7, 2.3, 2.8, 3.1, 3.2, 3.0]* *-- Finally, get a list of pairs (x,y), i.e. a list of points:* *ps = zip xs ys* *-- In this example, running "ps" we get, after rounding, the points: -- -- [(0, 0), (0.38, 0.46), (0.75, 1), (1.1, 1.7), -- (1.5, 2.3), (1.9, 2.8), (2.3, 3.1), (2.6, 3.2), (3, 3)] -- -- Now plot lines joining these points to get an approximation of the curve *
Salut,
Personne ne peut me répondre sur mon erreur ci-dessous?
comment caster de Float en Double?
J'ai d'autres questions:
Je n'ai pas très bien compris ce que signifie le '.
Apparemment ça a à voir avec l'impératif...
Je ne comprend pas très bien ce que font des opérateurs comme &&&:
(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c')
Dans la signature, que signifient les espaces entre les a,b,c...?
Merci!
Corentin
On 9/10/07, Dupont Corentin
J'ai tranformé mon programme de la manière suivante (voir ci-après). J'ai spécifié le type de la plupart des fonctions. Ca marche mieux, mais l'écriture est sérieusement plus lourde!
J'ai encore un problème:
courbe = defaultPlotLines { plot_lines_values = [[ (Point a b) | (a,b) <- ps]], plot_lines_style = solidLine lineWidth 0 0 1 }
donne l'erreur: Couldn't match expected type `Double' against inferred type `Float' In the first argument of `Point', namely `a' In the expression: (Point a b) In the expression: [(Point a b) | (a, b) <- ps]
en effet Point prend des doubles. Je n'ai pas trouvé de fonctions de conversion Float vers Double...
Merci! Corentin
module Lagrange where
nombre_points :: Integer nombre_points = 7
-- creation d'une liste exluant i list :: Integer -> [Integer] list i = filter (/=i) [0..nombre_points-1]
-- un terme du polynôme de Lagrange --un_terme :: Float -> Integer -> Integer -> Float un_terme t j i = (t - i_f)/(j_f - i_f) where i_f = fromInteger i j_f = fromInteger j
--produit des termes pour obtenir le polynôme d'un point les_termes t j = map (un_terme t j) (list j) poly t j = product (les_termes t j)
--blend (a,t) = a(0) * (poly t 0) + a(1) * (poly t 1) + a(2) * (poly t 2) + a(3) * (poly t 3) + -- a(4) * (poly t 4) + a(5) * (poly t 5) + a(6) * (poly t 6)
--t est le paramètre du polynôme, a sera la coordonnée (x ou y). blend_un_point :: Float -> (Integer -> Float) -> Integer -> Float blend_un_point t a numero_point = a(numero_point) * (poly t numero_point) blend_les_points t a = map (blend_un_point t a) [0..6]
blend :: (Integer -> Float, Float) -> Float blend (a,t) = sum (blend_les_points t a)
-- Sample points xy = [(-4.0,0.0), (-1.0,1.0), (-3.0,3.0), (0.0,4.0), (3.0,3.0),(1.0,1.0),(4.0,0.0)]
--creation des fonctions x et y x :: Integer -> Float x pos = fst (xy !! pos_Integer) where pos_Integer = fromInteger(pos) y :: Integer -> Float y pos = snd (xy !! pos_Integer) where pos_Integer = fromInteger(pos)
-- Blend the sample points for some given u: bx :: Float -> Float bx(u) = blend(x,u)
by :: Float -> Float by(u) = blend(y,u)
-- Take m+1 values for u, from 0 to nombre_points, equally spaced: us :: Integer -> [Float] us m = map (/mf) [0..6*mf] where mf = fromInteger m
-- For
m = 50
-- we get us(m)=[0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0].
-- Now get a list of points for the above values of the parameter:
xs = map bx (us(m)) ys = map by (us(m))
-- Running this, we get, where I've rounded the results to 2 digits: -- -- xs = [0.00, 0.38, 0.75, 1.1, 1.5, 1.9, 2.3, 2.6, 3.0] -- ys = [0.00, 0.46, 1.00, 1.7, 2.3, 2.8, 3.1, 3.2, 3.0]
-- Finally, get a list of pairs (x,y), i.e. a list of points:
ps = zip xs ys
-- In this example, running "ps" we get, after rounding, the points: -- -- [(0, 0), (0.38, 0.46), (0.75, 1), (1.1, 1.7), -- (1.5, 2.3), (1.9, 2.8), (2.3, 3.1), (2.6, 3.2), (3, 3)] -- -- Now plot lines joining these points to get an approximation of the curve
On 13/09/2007, Dupont Corentin
Personne ne peut me répondre sur mon erreur ci-dessous? comment caster de Float en Double?
je ne sais pas... peut-être realToFrac pour faire une conversion? l'hierarchie des classes dans http://en.wikibooks.org/wiki/Haskell/Class_declarations pourrait être pertinent sinon, tu peux aussi changer tes fonctions pour qu'elles acceptent Double, ou les généraliser: blend_un_point :: Float -> (Integer -> Float) -> Integer -> Float deviendra blend_un_point :: (Fractional a) => (Integer -> a) -> Integer -> a J'ignore la difference entre Fractional, Floating, etc
J'ai d'autres questions: Je n'ai pas très bien compris ce que signifie le '.
où? de temps en temps, on utilise x' ou foo' comme nom de variable. j'aime pas trop parce que je trouve le « ' » pas très visible, mais d'autres programmeurs ont l'air d'apprecier
Je ne comprend pas très bien ce que font des opérateurs comme &&&:
j'utilise les dessins dans http://en.wikibooks.org/wiki/Haskell/Understanding_arrows pour ça une utilisation de (&&&) de simplifier (f x, g x) en (f &&& g) x par abus de typage, on pourrait dire que (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) c'est à dire que (&&&) peut prend deux fonctions f et g; et un paramètre x, il appliquera f et g à x, et renovera le résultat dans un tuple. mais en fait, c'est en plus géneral que ça
(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c') Dans la signature, que signifient les espaces entre les a,b,c...?
Je sais pas comment ça s'appelle, mais tu as peut-être vu que il exist des types qui prennent des paramètres. Par exemple Maybe prend un variable a; donc si je donne Int au type Maybe, j'aurai le type Maybe Int. Either est un autre exemple, il prend deux parametrès. Ainsi, Either Int Float est un type. Par fois on écrit des fonctions qui marche avec des variables de types. Par exemple, la fonction fromMaybe :: a -> Maybe a -> a marche pour tous les paramètres qu'on peut donner au type Maybe Dans Haskell, tu peux écrire qqc encore plus general. Comparons fromMaybe :: a -> Maybe a -> a fromBlah :: (Blah x) => a -> x a -> a fromBlah marche pas seulement avec Maybe, mais avec tous les types «x» qui sont des instances de la class Blah. De façon similaire, (&&&) :: a b c -> a b c' -> a b (c,c') (&&&) marche pour les types «a» qui sont des instances d'Arrow, pas que pour les fonctions ((->) est un instance de Arrow parmi d'autres) On peut voir que la signature abusive que j'ai donné est similaire à la signature ci-dessus en la réecrivant: (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) (&&&) :: ((->) b c) -> ((->) b c') -> ((->) b (c, c')) (&&&) :: ((a) b c) -> ((a) b c') -> ((a) b (c,c')) -- je remplace « -> » par « a » (&&&) :: (a b c) -> (a b c') -> (a b (c,c')) (&&&) :: a b c -> a b c' -> a b (c,c') Si ça fait un peu bizzare de remplacer « -> » par « a », c'est utile de se rappeller que les types commes « , » sont des types comme des autres. C'est juste que là on utilise un opérateur pour le nom du type (comme on utilise (+) au lieu d'une fonction plus) Donc on pourrait imaginer... fst :: (x,y) -> x fst :: ((,) x y) -> x fstFoo :: (Foo a) => a x y -> x Ne fait pas trop confiance à mes propos; je suis loin d'être expert, et j'ai peut-être dit des bêtisses, ou utilisé des abus de langage sans savoir. -- Eric Kow http://www.loria.fr/~kow PGP Key ID: 08AC04F9 Merci de corriger mon français.
Merci Beaucoup ça m'éclaire bien!
Je ne suis pas encore très à l'aise avec ces histoires de classes de
types, c'est une généralisation qu'on ne voit pas trop dans les autres
languages ;)
Si j'ai bien compris, les types sont regroupés en classe en fonction
de leurs propriétés.
Eq pour les types qui supportent l'égalité (quel type ne supporte pas
l'égalité??)
Ord pour les types qu'on peut trier etc.
Certains types appartiennent à plusieurs classes donc?
OK, le ' n'est pas un opérateur
mais la virgule , oui! magnifique
Il faudra que je regarde cette classe Arrow, elle m'intrigue...
Merci encore
Je relirais ton message plusieurs fois pour bien imprimer tout ça ;)
Corentin
On 9/13/07, Eric Kow
On 13/09/2007, Dupont Corentin
wrote: Personne ne peut me répondre sur mon erreur ci-dessous? comment caster de Float en Double?
je ne sais pas... peut-être realToFrac pour faire une conversion? l'hierarchie des classes dans http://en.wikibooks.org/wiki/Haskell/Class_declarations pourrait être pertinent
sinon, tu peux aussi changer tes fonctions pour qu'elles acceptent Double, ou les généraliser: blend_un_point :: Float -> (Integer -> Float) -> Integer -> Float deviendra blend_un_point :: (Fractional a) => (Integer -> a) -> Integer -> a
J'ignore la difference entre Fractional, Floating, etc
J'ai d'autres questions: Je n'ai pas très bien compris ce que signifie le '.
où? de temps en temps, on utilise x' ou foo' comme nom de variable. j'aime pas trop parce que je trouve le « ' » pas très visible, mais d'autres programmeurs ont l'air d'apprecier
Je ne comprend pas très bien ce que font des opérateurs comme &&&:
j'utilise les dessins dans http://en.wikibooks.org/wiki/Haskell/Understanding_arrows pour ça
une utilisation de (&&&) de simplifier (f x, g x) en (f &&& g) x
par abus de typage, on pourrait dire que (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) c'est à dire que (&&&) peut prend deux fonctions f et g; et un paramètre x, il appliquera f et g à x, et renovera le résultat dans un tuple.
mais en fait, c'est en plus géneral que ça
(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c') Dans la signature, que signifient les espaces entre les a,b,c...?
Je sais pas comment ça s'appelle, mais tu as peut-être vu que il exist des types qui prennent des paramètres. Par exemple Maybe prend un variable a; donc si je donne Int au type Maybe, j'aurai le type Maybe Int. Either est un autre exemple, il prend deux parametrès. Ainsi, Either Int Float est un type. Par fois on écrit des fonctions qui marche avec des variables de types. Par exemple, la fonction fromMaybe :: a -> Maybe a -> a marche pour tous les paramètres qu'on peut donner au type Maybe
Dans Haskell, tu peux écrire qqc encore plus general. Comparons
fromMaybe :: a -> Maybe a -> a fromBlah :: (Blah x) => a -> x a -> a
fromBlah marche pas seulement avec Maybe, mais avec tous les types «x» qui sont des instances de la class Blah. De façon similaire, (&&&) :: a b c -> a b c' -> a b (c,c') (&&&) marche pour les types «a» qui sont des instances d'Arrow, pas que pour les fonctions ((->) est un instance de Arrow parmi d'autres)
On peut voir que la signature abusive que j'ai donné est similaire à la signature ci-dessus en la réecrivant:
(&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) (&&&) :: ((->) b c) -> ((->) b c') -> ((->) b (c, c')) (&&&) :: ((a) b c) -> ((a) b c') -> ((a) b (c,c')) -- je remplace « -> » par « a » (&&&) :: (a b c) -> (a b c') -> (a b (c,c')) (&&&) :: a b c -> a b c' -> a b (c,c')
Si ça fait un peu bizzare de remplacer « -> » par « a », c'est utile de se rappeller que les types commes « , » sont des types comme des autres. C'est juste que là on utilise un opérateur pour le nom du type (comme on utilise (+) au lieu d'une fonction plus)
Donc on pourrait imaginer...
fst :: (x,y) -> x fst :: ((,) x y) -> x fstFoo :: (Foo a) => a x y -> x
Ne fait pas trop confiance à mes propos; je suis loin d'être expert, et j'ai peut-être dit des bêtisses, ou utilisé des abus de langage sans savoir.
-- Eric Kow http://www.loria.fr/~kow PGP Key ID: 08AC04F9 Merci de corriger mon français.
_______________________________________________ Haskell-fr mailing list Haskell-fr@haskell.org http://www.haskell.org/mailman/listinfo/haskell-fr
J'ai d'autres questions bêtes:
- je n'ai pas trouvé d'opérateur / comme ceci:
(/) :: a -> a -> Maybe a
Pourtant il me semble que ce serait une bonne utilisation de Maybe
pour la division par zero?
Egalement je ne comprend pas pourquoi on appel ça la monade Maybe.
Pour moi une monade c'est une encapsulation d'une suite d'opérations
impératives...
Or là je vois le Maybe comme un sorte d'algèbre sur les types:
Maybe a c'est la "somme" de 2 types: "a" ou "rien".
N'hésitez pas à me dire si je polue la liste, je pose les questions un
peu comme elles me viennent ;)
Corentin
On 9/13/07, Dupont Corentin
Merci Beaucoup ça m'éclaire bien! Je ne suis pas encore très à l'aise avec ces histoires de classes de types, c'est une généralisation qu'on ne voit pas trop dans les autres languages ;)
Si j'ai bien compris, les types sont regroupés en classe en fonction de leurs propriétés. Eq pour les types qui supportent l'égalité (quel type ne supporte pas l'égalité??) Ord pour les types qu'on peut trier etc. Certains types appartiennent à plusieurs classes donc?
OK, le ' n'est pas un opérateur mais la virgule , oui! magnifique
Il faudra que je regarde cette classe Arrow, elle m'intrigue...
Merci encore Je relirais ton message plusieurs fois pour bien imprimer tout ça ;)
Corentin
On 9/13/07, Eric Kow
wrote: On 13/09/2007, Dupont Corentin
wrote: Personne ne peut me répondre sur mon erreur ci-dessous? comment caster de Float en Double?
je ne sais pas... peut-être realToFrac pour faire une conversion? l'hierarchie des classes dans http://en.wikibooks.org/wiki/Haskell/Class_declarations pourrait être pertinent
sinon, tu peux aussi changer tes fonctions pour qu'elles acceptent Double, ou les généraliser: blend_un_point :: Float -> (Integer -> Float) -> Integer -> Float deviendra blend_un_point :: (Fractional a) => (Integer -> a) -> Integer -> a
J'ignore la difference entre Fractional, Floating, etc
J'ai d'autres questions: Je n'ai pas très bien compris ce que signifie le '.
où? de temps en temps, on utilise x' ou foo' comme nom de variable. j'aime pas trop parce que je trouve le « ' » pas très visible, mais d'autres programmeurs ont l'air d'apprecier
Je ne comprend pas très bien ce que font des opérateurs comme &&&:
j'utilise les dessins dans http://en.wikibooks.org/wiki/Haskell/Understanding_arrows pour ça
une utilisation de (&&&) de simplifier (f x, g x) en (f &&& g) x
par abus de typage, on pourrait dire que (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) c'est à dire que (&&&) peut prend deux fonctions f et g; et un paramètre x, il appliquera f et g à x, et renovera le résultat dans un tuple.
mais en fait, c'est en plus géneral que ça
(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c') Dans la signature, que signifient les espaces entre les a,b,c...?
Je sais pas comment ça s'appelle, mais tu as peut-être vu que il exist des types qui prennent des paramètres. Par exemple Maybe prend un variable a; donc si je donne Int au type Maybe, j'aurai le type Maybe Int. Either est un autre exemple, il prend deux parametrès. Ainsi, Either Int Float est un type. Par fois on écrit des fonctions qui marche avec des variables de types. Par exemple, la fonction fromMaybe :: a -> Maybe a -> a marche pour tous les paramètres qu'on peut donner au type Maybe
Dans Haskell, tu peux écrire qqc encore plus general. Comparons
fromMaybe :: a -> Maybe a -> a fromBlah :: (Blah x) => a -> x a -> a
fromBlah marche pas seulement avec Maybe, mais avec tous les types «x» qui sont des instances de la class Blah. De façon similaire, (&&&) :: a b c -> a b c' -> a b (c,c') (&&&) marche pour les types «a» qui sont des instances d'Arrow, pas que pour les fonctions ((->) est un instance de Arrow parmi d'autres)
On peut voir que la signature abusive que j'ai donné est similaire à la signature ci-dessus en la réecrivant:
(&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) (&&&) :: ((->) b c) -> ((->) b c') -> ((->) b (c, c')) (&&&) :: ((a) b c) -> ((a) b c') -> ((a) b (c,c')) -- je remplace « -> » par « a » (&&&) :: (a b c) -> (a b c') -> (a b (c,c')) (&&&) :: a b c -> a b c' -> a b (c,c')
Si ça fait un peu bizzare de remplacer « -> » par « a », c'est utile de se rappeller que les types commes « , » sont des types comme des autres. C'est juste que là on utilise un opérateur pour le nom du type (comme on utilise (+) au lieu d'une fonction plus)
Donc on pourrait imaginer...
fst :: (x,y) -> x fst :: ((,) x y) -> x fstFoo :: (Foo a) => a x y -> x
Ne fait pas trop confiance à mes propos; je suis loin d'être expert, et j'ai peut-être dit des bêtisses, ou utilisé des abus de langage sans savoir.
-- Eric Kow http://www.loria.fr/~kow PGP Key ID: 08AC04F9 Merci de corriger mon français.
_______________________________________________ Haskell-fr mailing list Haskell-fr@haskell.org http://www.haskell.org/mailman/listinfo/haskell-fr
Le 13/09/07, Dupont Corentin
J'ai d'autres questions bêtes:
- je n'ai pas trouvé d'opérateur / comme ceci: (/) :: a -> a -> Maybe a
Pourtant il me semble que ce serait une bonne utilisation de Maybe pour la division par zero?
Ecrit le ? (/) est la division de réels pour l'instant, mais tu peux écrire : infixl 5 > a > 0 = Nothing a > b = Just $ a / b Et > deviendra ta division "sûre" dont tu parlais.
Egalement je ne comprend pas pourquoi on appel ça la monade Maybe. Pour moi une monade c'est une encapsulation d'une suite d'opérations impératives... Or là je vois le Maybe comme un sorte d'algèbre sur les types: Maybe a c'est la "somme" de 2 types: "a" ou "rien".
Tout à fait, Maybe a est un type somme Just a | Nothing, néanmoins Maybe est un instance de Monad parce que on peut donner un sens aux opérations monadiques sur le type Maybe (en fait plusieurs, mais celui qui a été choisi c'est :) : Nothing >>= f = Nothing Just a >>= f = f a return a = Just a Qui est assez pratique pour enchaîner un tas d'opération susceptible d'échouer sans devoir gérer soi-même les Maybe, autrement dit : addFromMap s1 s2 m = do a <- lookup s1 m b <- lookup s2 m return a + b renvoie Nothing si s1 ou s2 ne sont pas des clés de la Map m, ou Just le résultat de l'addition des valeurs correspondantes. (NB : Grâce à l'évaluation paresseuse et la définition de >>=, la fonction s'arrête en fait au premier échec et n'évalue pas la suite)
N'hésitez pas à me dire si je polue la liste, je pose les questions un peu comme elles me viennent ;)
Ne t'inquiète pas, tes questions sont les bienvenues, néanmoins tu obtiendrais sans doute des réponses plus rapides sur IRC (#haskell@irc.freenode.net). -- Jedaï
Le 13/09/07, Dupont Corentin
Pour moi une monade c'est une encapsulation d'une suite d'opérations impératives...
Cette définition a l'air un peu floue et assez inexacte en définitive. Une monade c'est juste un type et des opérations (>>=) et return sur ce type qui respectent les lois monadiques. Il y a un tas de tutorial sur le net et chacun les présentent à sa sauce, mais associer "impératif" et monade n'est pas juste, la monade IO introduit effectivement une succession d'opérations impures comme dans un programme impératif, néanmoins la plupart des monades ne sont nullement impures. -- Jedaï
Dupont Corentin wrote:
J'ai d'autres questions bêtes:
- je n'ai pas trouvé d'opérateur / comme ceci: (/) :: a -> a -> Maybe a
Pourtant il me semble que ce serait une bonne utilisation de Maybe pour la division par zero?
Ta question n'est nullement bête! La division par zéro n'est pas indéfinie en Haskell (IEEE), mais plutôt infinie:
Prelude> 3/0 Infinity
La plupart du temps ça correspond à ce que tu veux (bien que mathématiquement soupçonneux): Prelude> exp (-1/0) 0.0 Prelude> atan (1/0) 1.5707963267948966 Prelude> atan (-1/0) -1.5707963267948966 Le type Double contient l'infini comme valeur tout à fait respectable (au moins pour les architectures qui supportent le format IEEE), comme prevue dans: class (RealFrac a, Floating a) => RealFloat a where floatRadix :: a -> Integer floatDigits :: a -> Int floatRange :: a -> (Int, Int) decodeFloat :: a -> (Integer, Int) encodeFloat :: Integer -> Int -> a exponent :: a -> Int significand :: a -> a scaleFloat :: Int -> a -> a isNaN :: a -> Bool isInfinite :: a -> Bool isDenormalized :: a -> Bool isNegativeZero :: a -> Bool isIEEE :: a -> Bool atan2 :: a -> a -> a Dan
Salut, c'est encore moi
Egalement je ne comprend pas pourquoi on appel ça la monade Maybe. Pour moi une monade c'est une encapsulation d'une suite d'opérations impératives... Or là je vois le Maybe comme un sorte d'algèbre sur les types: Maybe a c'est la "somme" de 2 types: "a" ou "rien".
About monads: A monad is just an algebraic structure having two neccesary operations: bind (>>=) and return . For an other example the set of real numbers R is a ring having operations like + and * . And 0 and 1 if you need them are also here. But we may want to use the support set of an algebraic structure withaout taking care what this structure is. Somebodi in finance for example don't know anything about rings and other structures but he /she uses numbers from R daily. That's the case of Maybe: The set {Maybe a | a <- any type} U {Nothing} can be seen as a monad BY DEFINING PROPER monadic operations. But we can use only the datatype to represent computable or uncomputable (Nothing) values. Need to use Maybe ? Use it ! It's defined. Dan Popa ____________________________________________________________________________________ Shape Yahoo! in your own image. Join our Network Research Panel today! http://surveylink.yahoo.com/gmrs/yahoo_panel_invite.asp?a=7
Pour ma société, j'ai écrit une petite introduction à Haskell. Vos critiques sont les bienvenues. Je vous la fait lire: Titre : Présentation du langage Haskell Salut à tous ! Je me suis intéressé (à titre personnel) récemment à un nouveau langage de programmation généraliste : Haskell. L'article est à classer dans la catégorie « R&D » : Malgré tous les concepts intéressants qu'il introduit, il est encore peu utilisé dans le monde industriel. Mais il vaut le détour !! Haskell est un langage récent (moins d'une dizaine d'années). Quelques stats pour vous donner envie de lire la suite : - 10 fois moins de lignes de code qu'en C - Grande expressivité. - Compréhension, maintenabilité largement accrue. C'est un langage basé sur une théorie mathématique (la théorie de catégories). Ce langage est « fonctionnel pur », par opposition aux langages « impératifs », dont font parties tous les langages les plus connus (C, C++, Ada, Java, Pascal…). Cela induit un mode de programmation radicalement différent ! Haskell est : - paresseux - pleinement fonctionnel - fortement typé, et supporte l'inférence de type Haskell est effectivement paresseux, mais ce n'est pas péjoratif ! Cela signifie qu'il n'évalue pas une expression si ce n'est pas nécessaire. Si le résultat d'un calcul n'est pas utilisé dans la suite du programme, il n'est pas évalué. Cela induit un gain évident en terme de temps de traitement. Cela améliore aussi le design des programmes puisque cela décharge le programmeur de coder certaines optimisations, pour se concentrer sur le métier de son logiciel. Mais surtout, cela permet de faire certaines abstractions très intéressantes : comme par exemple des structures de données de taille infinie. En Haskell il est tout à fait possible de déclarer un « tableau » de taille infinie, par exemple un tableau contenant tous les éléments de la suite de Fibonacci ! Bien sûr vous choisirez de n'afficher que les n premiers éléments, et Haskell décidera de ne calculer que ceux là. (Voir l'exemple faramineux de wikipedia…) Ensuite Haskell est pleinement fonctionnel : les fonctions sont des objets de « 1ere classe ». Cela signifie que les fonctions peuvent être traitées comme des variables. Donc une fonction peut être passée en paramètre à une autre fonction, récupérée en paramètre de retour etc. Haskell supporte les fonctions anonymes et les fonctions « lambda ». Cela permet par exemple de décrire une fonction (simple) dans la zone de paramètres d'une autre fonction. Un bon exemple vaut mieux qu'un long discours : map (+1) [1..10] map est une fonction à 2 arguments : une fonction et une liste (ici [1..10]). Comme on peut s'y attendre, map applique la fonction à tous les éléments de la liste et retourne une liste résultante. Mais mais mais ??? « (+1) » c'est une fonction ? Eh bien oui, c'est une fonction anonyme (je ne l'ai pas déclarée avec un petit nom). Et la fonction « + » prend bien 2 arguments ? Je n'en voit qu'un (le 1 dans l'exemple)? Il s'agit du mécanisme d' « évaluation partielle » de Haskell. Si vous avez une fonction de 2 paramètres et que vous fournissez les 2 paramètres, super. Mais si vous ne fournissez qu'un paramètre, le résultat de l'opération sera… Une fonction bien sur ! Une fonction de l'autre paramètre. Et cette fonction à un paramètre est ce qu'attend la fonction map. Alors, quel est le résultat de cette ligne de code ? ;) Haskell supporte la curryfication. Cette opération, du nom de son inventeur, est à la base d'Haskell. D'ailleurs, devinez le prénom de ce Mr Curry… Haskell bien sur !! Il existe bien sùr une algèbre sur les fonctions : l'addition, la composition… Vous pouvez donc définir une fonction en une ligne par simple composition de deux autres fonctions à l'aide de l'opérateur rond « ° ». Ce qui rend les choses assez lisible : dans un gros programme les fonctionnalités de haut niveau sont souvent cassés en plusieurs fonctions plus simple. Une fois définis les fonctions simples, vous les ressemblez en une ligne avec l'opérateur rond. Haskell est statiquement et fortement typé. Le système de typage est très évolué, et vous évitera de nombreuses erreurs de programmation. Je termine par le plus dur : Haskell est un langage fonctionnel « pure ». Cela signifie qu'il n'y a aucuns effets de bords, et donc qu'il ne supporte pas l'affectation. Par exemple dans un programme en C, je pourrais avoir l'instruction suivante : a = f + g f et g sont des fonction, a un entier. Dans le cadre d'un refactoring, je pourrais être amené à vouloir écrire : a = g + f Eh bien ce n'est à priori pas possible car en C comme dans d'autres langages, les fonctions ont des effets de bord : f peut modifier le contexte qui sera utilisé par g. En Haskell, le retour d'une fonction dépend uniquement de ses paramètres, de rien d'autre. Si vous l'appelez à n'importe quel moment avec les mêmes paramètres, le résultat sera le même. Cela donne une très grande plasticité et maintenabilité au programme. Tout devient plus clair ! Mais il faut reconnaître que les programmes sont plus difficiles à écrire. Cette aspect « pas d'affectation » ouvre la porte à de nombreuses fonctionnalités impossible sans, dont la paresse. A noter aussi que comme conséquence, l'ordre des instructions n'a pas d'importance… Haskell est uniquement déclaratif. Haskell intègre aussi de nombreuses autres fonctionnalités que je n'ai malheureusement pas le temps de développer ici, dont : - la compréhension de listes - le pattern matching pour les paramètres - les monades et les classes de types… Références : www.haskell.org http://en.wikipedia.org/wiki/Haskell_(programming_language) Ouvrages de référence : Yet Another Haskell Tutorial A Gentle Introduction to Haskell Contrairement à ce que son nom indique, ce dernier ouvrage n'est pas gentil du tout, commencez plutôt par : Haskell for C Programmers
J'offre les quelques petites suggestions ci-dessous avec la précaution que le français n'est pas ma langue maternelle (ni Haskell non plus!) Dan Weston Dupont Corentin wrote:
Pour ma société, j'ai écrit une petite introduction à Haskell. Vos critiques sont les bienvenues. Je vous la fait lire:
Titre : Présentation du langage Haskell
Salut à tous !
Je me suis intéressé (à titre personnel) récemment à un nouveau langage de programmation généraliste : Haskell.
L'article est à classer dans la catégorie « R&D » : Malgré tous les concepts intéressants qu'il introduit, il est encore peu utilisé dans le monde industriel
mais jouit d'une croissance accélérante d'utilisation, ce qui promet un rôle de plus en plus important dans l'avenir.
. Mais il vaut le détour !! Haskell est un langage récent (moins d'une dizaine d'années).
Quelques stats pour vous donner envie de lire la suite : - 10 fois moins de lignes de code qu'en C - Grande expressivité. - Compréhension, maintenabilité largement accrue.
C'est un langage basé sur une théorie mathématique (la théorie de catégories). Ce langage est « fonctionnel pur », par opposition aux langages « impératifs », dont font parties tous les langages les plus connus (C, C++, Ada, Java, Pascal…). Cela induit un mode de programmation radicalement différent !
Haskell est :
- paresseux - pleinement fonctionnel - fortement typé, et supporte l'inférence de type
Haskell est effectivement paresseux, mais ce n'est pas péjoratif ! Cela signifie qu'il n'évalue pas une expression si ce n'est pas nécessaire. Si le résultat d'un calcul n'est pas utilisé dans la suite du programme, il n'est pas évalué.
En revanche, grâce à la transparence référentielle, le résultat d'une expression une fois évaluée peut être mémoizé (http://fr.wikipedia.org/wiki/M%C3%A9moization) et réutilisé ailleurs, évitant le coût de calculs redondants.
Cela induit un gain évident en terme de temps de traitement. Cela améliore aussi le design des programmes puisque cela décharge le programmeur de coder certaines optimisations, pour se concentrer sur le métier de son logiciel.
Mais surtout, cela permet de faire certaines abstractions très intéressantes : comme par exemple des structures de données de taille infinie. En Haskell il est tout à fait possible de déclarer un « tableau » de taille infinie, par exemple un tableau contenant tous les éléments de la suite de Fibonacci ! Bien sûr vous choisirez de n'afficher que les n premiers éléments, et Haskell décidera de ne calculer que ceux là. (Voir l'exemple faramineux de wikipedia…)
Ensuite Haskell est pleinement fonctionnel : les fonctions sont des objets de « 1ere classe ». Cela signifie que les fonctions peuvent être traitées comme des variables. Donc une fonction peut être passée en paramètre à une autre fonction, récupérée en paramètre de retour etc.
Haskell supporte les fonctions anonymes et les fonctions « lambda ». Cela permet par exemple de décrire une fonction (simple) dans la zone de paramètres d'une autre fonction. Un bon exemple vaut mieux qu'un long discours :
map (+1) [1..10]
map est une fonction à 2 arguments : une fonction et une liste (ici [1..10]). Comme on peut s'y attendre, map applique la fonction à tous les éléments de la liste et retourne une liste résultante. Mais mais mais ??? « (+1) » c'est une fonction ? Eh bien oui, c'est une fonction anonyme (je ne l'ai pas déclarée avec un petit nom).
Et la fonction « + » prend bien 2 arguments ? Je n'en voit qu'un (le 1 dans l'exemple)? Il s'agit du mécanisme d' « évaluation partielle » de Haskell. Si vous avez une fonction de 2 paramètres et que vous fournissez les 2 paramètres, super. Mais si vous ne fournissez qu'un paramètre, le résultat de l'opération sera… Une fonction bien sur ! Une fonction de l'autre paramètre. Et cette fonction à un paramètre est ce qu'attend la fonction map. Alors, quel est le résultat de cette ligne de code ? ;)
Haskell supporte la curryfication. Cette opération, du nom de son inventeur, est à la base d'Haskell. D'ailleurs, devinez le prénom de ce Mr Curry… Haskell bien sur !!
Il existe bien sùr une algèbre sur les fonctions : l'addition, la composition…
et la multiplication qui facilitent un style de programmation "point-free" [avec exemple?] [Mais la somme et le produit catégoriques de fonctions sont un peu complex pour cette introduction, peut-être qu'il vaut mieux omettre mention de l'addition entièrement.]
Vous pouvez donc définir une fonction en une ligne par simple composition de
[omis: deux autres]
fonctions à l'aide de l'opérateur rond « ° ». Ce qui rend les choses assez lisible : dans un gros programme les fonctionnalités de haut niveau sont souvent cassés en plusieurs fonctions plus simple. Une fois définis les fonctions simples, vous les ressemblez en une ligne avec l'opérateur rond.
La composition de fonctions étant toujours associative, on n'a même pas besoin de parenthèses.
Haskell est statiquement et fortement typé. Le système de typage est très évolué, et vous évitera de nombreuses erreurs de programmation.
Je termine par le plus dur : Haskell est un langage fonctionnel « pure ». Cela signifie qu'il n'y a aucuns effets de bords, et donc qu'il ne supporte pas l'affectation.
Par exemple dans un programme en C, je pourrais avoir l'instruction suivante :
a = f + g
f et g sont des fonction, a un entier. Dans le cadre d'un refactoring, je pourrais être amené à vouloir écrire :
a = g + f
Eh bien ce n'est à priori pas possible car en C comme dans d'autres langages, les fonctions ont des effets de bord : f peut modifier le contexte qui sera utilisé par g.
En Haskell, le retour d'une fonction dépend uniquement de ses paramètres, de rien d'autre. Si vous l'appelez à n'importe quel moment avec les mêmes paramètres, le résultat sera le même. Cela donne une très grande plasticité et maintenabilité au programme. Tout devient plus clair ! Mais il faut reconnaître que les programmes sont plus difficiles à écrire.
Cette aspect « pas d'affectation » ouvre la porte à de nombreuses fonctionnalités impossible sans, dont la paresse. A noter aussi que comme conséquence, l'ordre des instructions n'a pas d'importance… Haskell est uniquement déclaratif.
Les bénéfices d'un langage sans effects de bord ne peuvent que s'accroître avec l'arrivée des CPUs multiprocesseurs modernes.
Haskell intègre aussi de nombreuses autres fonctionnalités que je n'ai malheureusement pas le temps de développer ici, dont : - la compréhension de listes - le pattern matching pour les paramètres - les monades et les classes de types…
Références : www.haskell.org http://en.wikipedia.org/wiki/Haskell_(programming_language)
Ouvrages de référence : Yet Another Haskell Tutorial A Gentle Introduction to Haskell
Contrairement à ce que son nom indique, ce dernier ouvrage n'est pas gentil du tout, commencez plutôt par : Haskell for C Programmers _______________________________________________ Haskell-fr mailing list Haskell-fr@haskell.org http://www.haskell.org/mailman/listinfo/haskell-fr
On Thu, Sep 20, 2007 at 01:31:46PM -0700,
Dan Weston
En revanche, grâce à la transparence référentielle, le résultat d'une expression une fois évaluée peut être mémoizé (http://fr.wikipedia.org/wiki/M%C3%A9moization) et réutilisé ailleurs, évitant le coût de calculs redondants.
Oui, mais c'est surtout théorique. Le compilo ne le fait pas tout seul et, en pratique, c'est du travail de la part du programmeur que de mémoiser.
On 9/21/07, Stephane Bortzmeyer
On Thu, Sep 20, 2007 at 01:31:46PM -0700, Dan Weston
wrote a message of 195 lines which said: En revanche, grâce à la transparence référentielle, le résultat d'une expression une fois évaluée peut être mémoizé (http://fr.wikipedia.org/wiki/M%C3%A9moization) et réutilisé ailleurs, évitant le coût de calculs redondants.
Oui, mais c'est surtout théorique. Le compilo ne le fait pas tout seul et, en pratique, c'est du travail de la part du programmeur que de mémoiser.
Ah bon?? Comment ça? Et moi qui ai une mauvaise mémoire :(
_______________________________________________ Haskell-fr mailing list Haskell-fr@haskell.org http://www.haskell.org/mailman/listinfo/haskell-fr
Si je ne me trompe pas, dans les cas suivants: f x = ... let f x = ... where f x = ... l'évaluation de (f x) est automatiquement mémoisée par GHC pour chaque instance de x. Par contre, let f = (+1) in f x ne mémoize pas (f x). Pour être certain de ce que fait le compilo GHC, tu peux poser la question à Glasgow-haskell-users. Moi, je n'y suis pas souscrit. Dan Stephane Bortzmeyer wrote:
On Thu, Sep 20, 2007 at 01:31:46PM -0700, Dan Weston
wrote a message of 195 lines which said: En revanche, grâce à la transparence référentielle, le résultat d'une expression une fois évaluée peut être mémoizé (http://fr.wikipedia.org/wiki/M%C3%A9moization) et réutilisé ailleurs, évitant le coût de calculs redondants.
Oui, mais c'est surtout théorique. Le compilo ne le fait pas tout seul et, en pratique, c'est du travail de la part du programmeur que de mémoiser.
_______________________________________________ Haskell-fr mailing list Haskell-fr@haskell.org http://www.haskell.org/mailman/listinfo/haskell-fr
On Thu, Sep 20, 2007 at 02:55:28PM +0200,
Dupont Corentin
Pour ma société, j'ai écrit une petite introduction à Haskell.
Tiens, moi aussi :-) http://www.bortzmeyer.org/haskell-expose-fr.html
Ah oui, très bon, j'avais déjà vu ta présentation ;)
Le soucis, c'est que je suis dans une boite de services, donc nous
sommes plutôt "suiveurs" en matière de technologies!
Alors Haskell, faut pas y compter tout de suite...
On 9/21/07, Stephane Bortzmeyer
On Thu, Sep 20, 2007 at 02:55:28PM +0200, Dupont Corentin
wrote a message of 158 lines which said: Pour ma société, j'ai écrit une petite introduction à Haskell.
Tiens, moi aussi :-)
--- Dupont Corentin
Salut,
Personne ne peut me répondre sur mon erreur ci-dessous? comment caster de Float en Double?
If you really need a datatype for a Point you may use something like : Num a => Point a a specifying that: I) a may be every numeric type and II) a point is something which includes 2 pieces of date which belongs to that type a. As a result the system will use the needed kind of points everywhere. 2)
J'ai d'autres questions: Je n'ai pas très bien compris ce que signifie le '. Apparemment ça a à voir avec l'impératif...
Nothing special. It is like _ in other languages.
Je ne comprend pas très bien ce que font des opérateurs comme &&&: (&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c') Translation: In the hypothesis that a is a type froma a class of types called Arrow then the type of the &&& function (operator) is: a b c -> a b c' -> a b (c, c')
Remark: you may presume that a and b are type constructors (like m for monads). So: a b c means: the a type constructor applied to ( b type constructor applied to a data fromthe type c). This is a complex datatype. a b c' means: the a type constructor applied to ( b type constructor applied to a data the type c'). This is a complex datatype. c' may or may not be the same with c. a b (c, c') means: the a type constructor applied to ( b type constructor applied to the pair formed by last c and last c'). This is a complex datatype. c' may or may not be the same with c but both are the previously c and c', now alltogether. (c,c') means: pair made by c and c'
Dans la signature, que signifient les espaces entre les a,b,c...?
Application of the typeconstructor from the left to the datatype from the right. It's something like: a(b(c)) in mathematics.
Merci! Corentin
You are wellcome ! Dan P.S. Can I use the question rised, for example as examples for my students or by posting them to haskell.org in any language ? Or would you like to translate the explanations in french for Haskell-fr ? ____________________________________________________________________________________ Pinpoint customers who are looking for what you sell. http://searchmarketing.yahoo.com/
BIen sur, tu peut utiliser mes questions ;)
Et merci pour les réponses!
On 9/18/07, Dan Popa
--- Dupont Corentin
wrote: 1)
Salut,
Personne ne peut me répondre sur mon erreur ci-dessous? comment caster de Float en Double?
If you really need a datatype for a Point you may use something like :
Num a => Point a a
specifying that: I) a may be every numeric type and II) a point is something which includes 2 pieces of date which belongs to that type a. As a result the system will use the needed kind of points everywhere.
2)
J'ai d'autres questions: Je n'ai pas très bien compris ce que signifie le '. Apparemment ça a à voir avec l'impératif...
Nothing special. It is like _ in other languages.
Je ne comprend pas très bien ce que font des opérateurs comme &&&: (&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c') Translation: In the hypothesis that a is a type froma a class of types called Arrow then the type of the &&& function (operator) is: a b c -> a b c' -> a b (c, c')
Remark: you may presume that a and b are type constructors (like m for monads). So: a b c means: the a type constructor applied to ( b type constructor applied to a data fromthe type c). This is a complex datatype. a b c' means: the a type constructor applied to ( b type constructor applied to a data the type c'). This is a complex datatype. c' may or may not be the same with c.
a b (c, c') means: the a type constructor applied to ( b type constructor applied to the pair formed by last c and last c'). This is a complex datatype. c' may or may not be the same with c but both are the previously c and c', now alltogether.
(c,c') means: pair made by c and c'
Dans la signature, que signifient les espaces entre les a,b,c...?
Application of the typeconstructor from the left to the datatype from the right. It's something like: a(b(c)) in mathematics.
Merci! Corentin
You are wellcome ! Dan
P.S. Can I use the question rised, for example as examples for my students or by posting them to haskell.org in any language ?
Or would you like to translate the explanations in french for Haskell-fr ?
____________________________________________________________________________________ Pinpoint customers who are looking for what you sell. http://searchmarketing.yahoo.com/
participants (9)
-
Chaddaï Fouché -
Dan Popa -
Dan Weston -
david48 -
Dupont Corentin -
Dupont Corentin -
Eric Kow -
Eric Y. Kow -
Stephane Bortzmeyer