# [Haskell-cafe] Newbie: Is‘type’ synonym hiding two much?

Dmitri O.Kondratiev dokondr at gmail.com
Thu Mar 22 11:13:00 EDT 2007

I am learning Haskell working through Simon Thompson book "Haskell The Craft
of Functional Programming" (second edition). Solving problems in the book
with more or less success I arrived almost to the end of the book at the
section 17.5 "Case study: parsing expressions".
Most probably the question I am going to ask here is very stupid, so please
bear with me. In any case, after going so far in the book I felt certain
that I know what function declaration means. So I thought that declaration:

F :: a -> b -> c

Is the same as:

F :: a -> (b -> c)

And means either:

-    a function 'f' of one argument of type 'a' that returns a function of
type (b -> c), or it can also be interpreted as:
-    a function 'f' of two arguments of type 'a' and 'b' returning value of
type 'c'

Now, in the 17.5 section of a book one may see the following declarations:

succeed :: b -> Parse a b

*Before looking at 'succeed' function definition* one may think that
'succeed' is a function of *one* argument of type 'b' that returns object of
type 'Parse a b'.

Yet, function definition given in the book is:

succeed val inp = [(val, inp)]

Looking at this definition, I am inclined to think that 'succeed' is a
function of *two*  arguments named 'val' and 'inp' in the definition !
How can such a definition be correct?

Ok, lets see what is this 'Parse a b' type is:

type Parse a b = [a] -> [(b, [a])]

So how does this help to make definition

'succeed val inp = [(val, inp)]'

sound right?

Well, the only way for me to make sense out of this is as follows.
In this case Haskell 'type' makes type synonym for the type:
[a] -> [(b, [a])]

In order not to get out of my mind I start thinking about 'type' as a macro
substitution mechanism. Then I do this substitution *myself as a Haskell
runtime* and get in the result the following declaration of a * real
function that Haskell runtime* works with:

Succeed :: b -> [a] -> [(b, [a])]

Great! This last declaration matches perfectly with function definition:

succeed val inp = [(val, inp)]

So I start feeling better, after all, it looks like my understanding of
Haskell function declarations is not flawed too much.
Well, but here comes my main questions! So:
1. Should I work every time as a macro translator when I just see *!any!*
function declaration?
2. Should I search through main and imported modules for treacherous 'type'
constructs?
3. Where, in this case goes implementation abstraction principle? Why I must
provide *all* the details about function argument type structure in order to
understand how this function works?

Another example of a similar function from the book is:

alt :: Parse a b -> Parse a b -> Parse a b
alt p1 p2 inp = p1 inp ++ p2 inp

In function definition I see three parameters:
p1 – matches with function declaration perfectly
p2 – matches with function declaration perfectly
inp – how to match this parameter with function declaration ?

I can match 'inp' parameter with 'alt' function declaration *only* after
working as macro processor that expands type synonym 'Parse a b' into '[a]
-> [(b, [a])]' and getting *real* declaration:

alt :: [a] -> [(b, [a])] -> [a] -> [(b, [a])] -> [a] -> [(b, [a])]

with that matches

alt p1 p2 inp = p1 inp ++ p2 inp

where 'inp' matches with *last* '[a]' argument.

It seems that life of "human macro processor" becomes really hard when not
trivial functions with 'type' synonym arguments come into play!
Where I am wrong? Please enlighten me; I am really at a loss!
And thanks for reading all this!
Below I give a code example of these functions.

Thanks,
Dima

module Parser where

import Data.Char

type Parse a b = [a] -> [(b, [a])]

none :: Parse a b
none inp = []

succeed :: b -> Parse a b
succeed val inp = [(val, inp)]

suc:: b -> [a] -> [(b, [a])]
suc val inp = [(val, inp)]

spot :: (a -> Bool) -> Parse a a
spot p [] = []
spot p (x:xs)
| p x = [(x, xs)]
| otherwise = []

alt :: Parse a b -> Parse a b -> Parse a b
alt p1 p2 inp = p1 inp ++ p2 inp

bracket = spot (=='(')
dig = spot isDigit

t1 = (bracket `alt` dig) "234"
-------------- next part --------------
An HTML attachment was scrubbed...