[Haskell-beginners] Question on Real World Haskell ch.13 SymbolicManip

Mike Meyer mwm at mired.org
Wed Jun 1 03:20:10 CEST 2011

On Tue, 31 May 2011 20:48:41 -0400
Jake Penton <djp at arqux.com> wrote:

> Greetings. I post here from time to time as I work my way through Real World Haskell. I believe that I have understood most of what I have studied. However, today I ran into something that seems like magic.
> I hope it's ok to refer to RWH here, as I believe that the book is very commonly used for learning the language. I'll include the code that is puzzling me here anyway, though.
> On p.310 of RWH we have:
> data Op = Plus | Minus | Mul | Div | Pow
>         deriving (Eq, Show)
> data SymbolicManip a = 
>     Number a
>   | Arith Op (SymbolicManip a) (SymbolicManip a)
>     deriving (Eq, Show)
> instance Num a => Num (SymbolicManip a) where
>     a + b = Arith Plus a b
>     a - b = Arith Minus a b
>     a * b = Arith Mul a b
>     negate a = Arith Mul (Number (-1)) a
>     abs a = error "abs is unimplemented"
>     signum _ = error "signum is unimplemented"
>     fromInteger i = Number (fromInteger i)
> Ok, so far so good. But the following example seems quite astounding to me:
> ghci> (5 * 10 + 2)::SymbolicManip Int
> Arith Plus (Arith Mul (Number 5) (Number 10)) (Number 2)
> The book says to notice that haskell "converted" 5 * 10 + 2 into a SymbolicManip. Indeed!
> My understanding breaks down at this point. I suspect that it may be my weak grasp of the implications of lazy evaluation, and typeclasses generally. My (incorrect) intuition makes me think that the stuff inside the parentheses should be evaluated first, and then typed as a SymbolicManip. This would give the result Number 52. 
> My question may be too vague to answer easily, but what I am hoping for is a bit of a narrative regarding how haskell knows that the pieces inside the parentheses are each of type SymbolicManip Int. Or something like that....

I'm working through the book as well (at least, when I'm not otherwise
occupied), so will take a stab at an answer to see if *I* understand
it properly.

This doesn't have anything to do with lazy evaluation, but with type
inferencing. The type of the entire expression is "SymbolicManip Int"
(SMI from now on) because - well, you said it is. Since the type of
the expression is SMI, the type of (X + 2) must be SMI, which means
the (+) function has to produce that result type, and the only
function that does that is the SMI instance of Num. Since it's two
arguments are of type SMI, the sub-expression (5 * 10) gets the same
treatment, and then all of the integers gets turned into an SMI using
the function specified by fromInteger because they also have to be of
type SMI.

Mike Meyer <mwm at mired.org>		http://www.mired.org/
Independent Software developer/SCM consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

More information about the Beginners mailing list