I'm new to Haskell and functional programming; have been
exploring the fixed-point combinator based on the exercise in the HSOE book.
Having an odd issue with typing in ghci which I don't understand - maybe it's
to do with section 3.4.5. "Type defaulting in GHCi"
but I don't really grok that yet…
(BTW, an unrelated question: is there a good reference
where I can understand the precendence/associativity rules for Haskell? I
continually find myself needing lots of parens before expressions behave as I
expect, and get very confused trying to use the $ operator - usually resorting
to lots of parens again :-)
My typing question might boil down to this simple example,
though my original example follows:
-- Why don't these (particularly g and g') all have the same
type?
Prelude> :t (\x -> x+1)
(\x -> x+1) :: (Num a) => a -> a
Prelude> let g = (\x -> x+1)
Prelude> :t g
g :: Integer -> Integer
Prelude> let g' x = x + 1
Prelude> :t g'
g' :: (Num a) => a -> a
-- Here's my original fixed-point combinator example:
Prelude> let fix f = f (fix f)
-- here's a silly (but working) implementation of length
using fix:
Prelude> fix (\g xs -> if xs == [] then 0 else
(1 + g (tail xs))) [1,2,3,4]
4
-- so I examine the types of the parts, which seems fine:
Prelude> :t fix (\g xs -> if xs == [] then 0 else (1 +
g (tail xs)))
… :: (Num t, Eq a) => [a] -> t
Prelude> :t (\g xs -> if xs == [] then 0 else (1 + g
(tail xs)))
… :: (Num t, Eq a) => ([a] -> t) -> [a] ->
t
-- but now I try to bind the anonymous function to a name
-- this seems to get the types wrong and no longer works as
I expect:
Prelude> let lenstep = (\g xs -> if xs == [] then 0
else (1 + g (tail xs)))
Prelude> :t lenstep
lenstep :: ([()] -> Integer) -> [()] -> Integer
Prelude> :t fix lenstep
fix lenstep :: [()] -> Integer
Prelude> let len' = fix (\g xs -> if xs == [] then 0
else (1 + g (tail xs)))
Prelude> :t len'
len' :: [()] -> Integer
Prelude>
Prelude> len' [1,2,3,4]
<interactive>:1:12:
No instance for (Num ())
arising from the literal `4'
at <interactive>:1:12
Possible fix: add an instance declaration
for (Num ())
In the expression: 4
In the first argument of `len'', namely
`[1, 2, 3, 4]'
In the expression: len' [1, 2, 3, 4]
-- maybe this is just me not understanding name binding
properly; it seems to work if I do it this way:
Prelude> let lenstep' g xs = (if xs == [] then 0 else (1
+ g (tail xs)))
Prelude> :t lenstep'
lenstep' :: (Eq a, Num t) => ([a] -> t) -> [a]
-> t
Prelude> :t fix lenstep'
fix lenstep' :: (Eq a, Num t) => [a] -> t
Prelude> fix lenstep' [1,2,3,4]
4
-- but what's the difference?
Cheers,
Patrick
Patrick.Surry@portraitsoftware.com,
VP Technology Tel: (617) 457 5230 Mob: (857) 919 1700 Fax: (617) 457
5299 Map Portrait Software introduces Portrait Campaign Manager: Easy, integrated campaign management for automated and highly
targeted outbound marketing |