[Haskell-beginners] Multiple type numeric data

David Virebayre dav.vire+haskell at gmail.com
Mon Nov 2 04:49:34 EST 2009


On Sun, Nov 1, 2009 at 6:53 PM, Didier Jacquemart
<didier.jacquemart at free.fr> wrote:

> data Figure = Carre Int Int Int
>         | Rond (Int, Int, Integer)    -- i hope Integer allows fromInteger

> surface_carre :: Figure -> Int
> surface_carre (Carre x y c)= c * c

> surface_rond :: Figure -> Float
> surface_rond  (Rond (x, y, r))= 3.14  * r * r

> surface x = case x of
>   Carre a b c     -> surface_carre x
>   Rond  (a, b, c) -> surface_rond x

> a::Figure
> a=Carre 10 10 5
> b::Figure
> b=Rond (20, 20, 3)

> When i load this program, i get the following error for the line 3.14 * r *
> r
>
> Couldn't match expected type Float
>           against inferred type Integer
> In the expression : 3.14 *r * r
> ...

Salut, ton problème c'est que la valeur de retour de surface_rond est
float, mais le rayon est integer.
Le fait est que Haskell ne veut pas mixer des integer avec des floats
sans explicitement lui demander de les convertir.

donc surface_rond (Rond (x,y,r)) = 3.14 * ( fromIntegral r) * ( fromIntegral r)

mais comme on veut éviter de calculer le fromIntegral r deux fois, il
vaut mieux écrire

surface_rond (Rond (x,y,r)) = let r' = fromIntegral r in 3.14 * r' * r'


Ensuite, tu vas avoir un problème avec la fonction surface : la valeur
de retour de surface est soit int, soit float, selon si surface_carre
ou surface rond est appelée.
Or, c'est invalide. Il te faut choisir un type. le plus général étant
float, tu as deux solutions:
1) modifier surface_carre pour que cela retourne un float
2) convertir, dans la fonction surface, la valeur de retour de
surface_carre en float.

Cela donne :

cas 1) modifier la fonction surface_carre mais pas la fonction surface

surface_carre (Carre _ _ c) = let c' = fromIntegral c in c' * c'

Note que comme tu n'utilise pas les paramètres x et y, tu peux
indiquer au compilateur que tu n'en a pas besoin en utilisant un _ au
lieu de les nommer.

cas 2) modifier la fonction surface mais pas surface_carre

surface x = case x of
  Carre _ _ _     -> fromIntegral $ surface_carre x
   Rond  (_, _, _) -> surface_rond x

A mon avis, tu n'a pas besoin des fonctions surface_carre et
surface_rond, tu peux définir surface comme suit.

surface (Carre _ _ c ) =  let c' = fromIntegral c in c' * c'
surface (Rond (_ _ r) =   let r' = fromIntegral r in 3.14 * r' * r'

D'ailleurs par curiosité, dans la définition de figure, pourquoi
définis-tu Rond avec les paramètres entre parenthèses ( un triple )
alors que tu ne le fais pas pour Carre ?

David.


More information about the Beginners mailing list