Question to chapter nine

5 views
Skip to first unread message

David Fries

unread,
Feb 8, 2009, 8:25:31 AM2/8/09
to Real World Haskell Book Club
Hi everybody. I have some trouble wrapping my head around some of the
examples in that chapter. If sessions are still being held, I'd wait
till chapter nine is discussed.

Andrew Wagner

unread,
Feb 8, 2009, 4:51:20 PM2/8/09
to real-world-has...@googlegroups.com
Any in particular giving you trouble? Can you say what you're confused about? I'll gladly to try to help out on the list if I can.

David Fries

unread,
Feb 9, 2009, 12:37:55 PM2/9/09
to Real World Haskell Book Club
Thanks. Specifically I was thinking of the examples about predicates.
In the section about the domain specific embedded language to search
the file system (on the pages 222, 223). The book defines a generic
predicate-like type InfoP a. This "type is just a synonym for a
function of four arguments".

type InfoP a = FilePath -- path to directory entry
-> Permissions -- permissions
-> Maybe Integer -- file size (Nothing if not file)
-> ClockTime -- last modified
-> a

A little later the equalP function is given as:

equalP :: (Eq a) => InfoP a -> a -> InfoP Bool
equalP f k = \w x y z -> f w x y z == k

I don't understand what values are bound to the variables f, k, w, x,
y and z. I believe that 'InfoP a' is bound to f and 'a' is bound to k
(ignoring w x y z for the moment) But how can that be if InfoP is just
a type synonym of a function? Shouldn't the signature of equalP be

equalP :: (Eq a) => (InfoP a) -> a -> InfoP Bool

... if you wanted to pass in a function as argument? (Or
alternatively, shouldn't you have to pass four arguments instead of
only one)? To check, I added parentheses to the signature of equalP
expecting that GHC would throw some kind of error which might give me
additional clues. But the code compiled nicely. What am I missing
here?

Then there are w, y, x and z. IMO horrible picks for variable names -
even inside a lambda expression. I assume these are parameters of the
function that is created in the lambda expression. This would imply
that the compiler is smart enough to figure out the correct types
based on the declared InfoP Bool return type. Is that correct?

Dan Schmidt

unread,
Feb 9, 2009, 12:50:11 PM2/9/09
to real-world-has...@googlegroups.com
equalP is a function that takes an InfoP a, which is a function,
(FilePath -> Permissions -> Maybe Integer -> ClockTime -> a) and an a,
and returns an InfoP Bool (FilePath -> Permissions -> Maybe Integer ->
ClockTime -> a), which is another function.

"\w x y z -> f w x y z == k" is the definition of that function that
it is returning.

This function takes a FilePath w, a Permissions x, a Maybe Integer y,
and a ClockTime z, calls f on them which results in a value of type a,
and then compares that result against k.

The alternative type signature for equalP that you give is equivalent;
the parentheses don't change the meaning.

I'm not sure what you mean by "I believe that 'InfoP a' is bound to f
and 'a' is bound to k". f is a value of type InfoP a and k is a value
of type a.

Andrew Wagner

unread,
Feb 9, 2009, 12:54:09 PM2/9/09
to real-world-has...@googlegroups.com
It looks to me like you're understanding almost everything perfectly. I agree, the parameter names maybe could be improved, but you've grasped correctly what's going on. The two type signatures:

equalP :: (Eq a) => InfoP a -> a -> InfoP Bool
and
equalP :: (Eq a) => (InfoP a) -> a -> InfoP Bool

are, in fact, identical. The reason the parentheses aren't needed are because type construction "binds" more tightly than function typing, if you want to think about it like that. What might be confusing you (just a shot in the dark) is the difference between this and a signature like:

map :: (a -> b) -> [a] -> [b]

Why are the parens needed here? Well, you can see now that this is a little bit different case. We're binding the function application together on the left and the right, so we need the parens to make it not bind incorrectly (function declaration is right-associative by default).

I hope this helps.

On Mon, Feb 9, 2009 at 12:37 PM, David Fries <d...@gmx.ch> wrote:

David Fries

unread,
Feb 9, 2009, 4:34:42 PM2/9/09
to Real World Haskell Book Club
Thanks for clearing that guys!

What threw me off was the type synonym. The books says that the InfoP
a type is only introduced so that we don't have to write the whole
signature every single type. In my mental image I simply replaced all
occurrences of 'InfoP a' by the signature it represents. It didn't
even occur to me that defining a type synonym creates a new type
constructor...

Just to make sure I understand you correctly, the 'InfoP a'
constructor has a higher precedence than ->. That's the reason the
parens are not required. Right?

Andrew Wagner

unread,
Feb 9, 2009, 4:47:42 PM2/9/09
to real-world-has...@googlegroups.com
Yes, but only InfoP is the type constructor, the 'a' is a type parameter passed to it. 
Reply all
Reply to author
Forward
0 new messages