Send Beginners mailing list submissions to
[email protected]
To subscribe or unsubscribe via the World Wide Web, visit
http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."
Today's Topics:
1. Re: Parsec, comma sperated list with special last element
(Karl Voelker)
2. Re: Parsec, comma sperated list with special last element
(Nathan H?sken)
3. Understanding Type Synonyms, Church Booleans, and Church
Numbers (Costello, Roger L.)
----------------------------------------------------------------------
Message: 1
Date: Mon, 17 Dec 2012 23:21:14 -0800
From: Karl Voelker <[email protected]>
Subject: Re: [Haskell-beginners] Parsec, comma sperated list with
special last element
To: Nathan H?sken <[email protected]>
Cc: Haskell Beginners <[email protected]>
Message-ID:
<CAFfow0wPP8R98tsgAv43DnPx4bfCR7eYnNFRmcQLZRGiv0mS=w...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
On Mon, Dec 17, 2012 at 2:28 AM, Nathan H?sken <[email protected]>wrote:
> Still ... I can not do it with "endBy", can I?
>
I think you can. What have you tried with endBy that didn't work?
-Karl
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20121217/7e43f25b/attachment-0001.htm>
------------------------------
Message: 2
Date: Tue, 18 Dec 2012 09:58:45 +0100
From: Nathan H?sken <[email protected]>
Subject: Re: [Haskell-beginners] Parsec, comma sperated list with
special last element
To: Karl Voelker <[email protected]>
Cc: Haskell Beginners <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1
I tried
file = do
res <- endBy (try cell) (char ',')
l <- lastCell
eof
return res
cell = many1 (noneOf ",")
lastCell = many1 (noneOf "\n")
But that does not work because cell succeeds on the last cell.
I can replace the endBy by
many (try $ do {a <- cell; string ","; return a})
Nathan
On 12/18/2012 08:21 AM, Karl Voelker wrote:
> On Mon, Dec 17, 2012 at 2:28 AM, Nathan H?sken
> <[email protected]>wrote:
>
>> Still ... I can not do it with "endBy", can I?
>>
>
> I think you can. What have you tried with endBy that didn't work?
>
> -Karl
>
------------------------------
Message: 3
Date: Tue, 18 Dec 2012 10:29:01 +0000
From: "Costello, Roger L." <[email protected]>
Subject: [Haskell-beginners] Understanding Type Synonyms, Church
Booleans, and Church Numbers
To: "[email protected]" <[email protected]>
Message-ID:
<[email protected]>
Content-Type: text/plain; charset="us-ascii"
Hi Folks,
The following is my summary of section 3.7 of Richard Bird's book,
"Introduction to Functional Programming using Haskell."
In most programming languages Booleans and numbers are built-in values. But
suppose they weren't, how would you implement decisions and how would you do
'some thing' a number of times?
Alonzo Church realized in the 1940's that Boolean and numeric values can be
implemented as functions. In fact, he realized that the function is the only
primitive needed in a programming language.
Functions that implement Boolean values are known as Church Booleans (Cbool)
and functions that implement numeric values are known as Church numbers (Cnum).
Below I show how to implement the Boolean true and false values as functions.
Then I show to implement the logical functions 'and', 'or', and 'not' so that
they operate on the true and false functions.
-------------------------------
The Cbool Type Synonym
-------------------------------
First I define a type synonym 'Cbool a'. It is a synonym for any function that
takes two arguments of the same type and returns a result of the same type:
type Cbool a = a -> a -> a
Notice that it is a parameterized type synonym which means that it can be
customized by replacing 'a' with any type. For example, 'Cbool Integer' is a
synonym for any function that takes two arguments of type Integer and returns a
result of type Integer:
Integer -> Integer -> Integer
Interestingly, the 'a' can be replaced with 'Cbool a'. So 'Cbool (Cbool a)' is
a synonym for any function that takes two arguments of type 'Cbool a' and
returns a result of type 'Cbool a':
Cbool a -> Cbool a -> Cbool a
The benefit of using type synonyms is that it enables us to work at a higher
level of abstraction. Rather than working with "a function that takes two
arguments of the same type and returns a result of the same type" we simply
work with "the Cbool type" just as though it was a built-in type. That's nice.
---------------------------------
Functions for true and false
---------------------------------
What are the truth values - true and false - actually for? One might answer
that they are for making decisions, for choosing between a pair of alternatives
(x, y):
if true then x else y
We can capture this impression by defining true and false as functions. Here's
how:
true is a function that picks the first alternative x.
false is a function that picks the second alternative y.
So true and false take two arguments of the same type and return a result of
the same type. Hey, that's the Cbool type. So true and false are Cbool types.
true, false :: Cbool a
true x y = x -- true returns the first
alternative
false x y = y -- false returns the second
alternative
Let's experiment with the Cbool type synonym and with the true and false
functions.
Below is a function, test1, which takes one argument - a Cbool Integer - and
returns an Integer.
That is, test1 is a function that takes one argument - a function that takes
two Integer arguments and returns an Integer - and returns an Integer.
test1 :: Cbool Integer -> Integer
test1 f = f 1 2
Since true and false are of type Cbool a, they are also of type Cbool Integer
and therefore can be used as the argument to test1:
t1 = test1 true -- returns 1
t2 = test1 false -- returns 2
Observe that (+) is a function which takes two numeric arguments and returns a
numeric result. So (+) is also a Cbool type:
(+) :: Cbool Num
t3 = test1 (+) -- returns 3
The following function, test1' is equivalent to test1 except it doesn't use the
Cbool type synonym.
test1' :: (Integer -> Integer -> Integer) -> Integer
test1' f = f 1 2
t1' = test1' true -- returns 1
t2' = test1' false -- returns 2
t3' = test1' (+) -- returns 3
test1' is much less attractive than test1.
'Cbool Integer' is a nice compact type name that shields us from the underlying
complexity and enables us to work at a higher level of abstraction.
Now let's see how to implement the logical operators 'not', 'and', and 'or' so
that they operate on our true and false functions.
-----------------------
Implementing 'not'
-----------------------
'not' will be defined as a function which takes one argument that is of type
Cbool.
Specifically, not's argument is 'Cbool a', where 'a' is 'Cbool a'.
So, not's argument is a function that takes two 'Cbool a' arguments and returns
a 'Cbool a'.
not :: Cbool(Cbool a) -> Cbool a
Recall that true and false are of type Cbool a. We've seen that 'a' can be
Integer. But 'a' can be any type, including Cbool a. So the true and false
functions are suitable arguments for the 'not' function.
Here is the behavior we desire of the 'not' function: If not's argument is
true, then return false. If not's argument is false, then return true. This
function does the job:
not :: Cbool(Cbool a) -> Cbool a
not f = f false true
t4 = not true -- returns function false
t5 = t4 1 2 -- returns 2
------------------------
Implementing 'and'
------------------------
'and' is a function that takes two arguments. The first argument chooses
between the second argument and false. If the first argument is true, then
return the second argument. If the first argument is false, then return false.
and :: Cbool(Cbool a) -> Cbool a -> Cbool a
and f g = f g false
t6 = and true true -- returns function true
t7 = and true false -- returns function false
t8 = and false true -- returns function false
t9 = and false false -- returns function false
t10 = true `and` true -- returns function true (notice that infix
notation is being used)
----------------------
Implementing 'or'
----------------------
'or' is a function that takes two arguments. The first argument chooses between
true and the second argument. If the first argument is true, then return true.
If the first argument is false, then return the second argument.
or :: Cbool(Cbool a) -> Cbool a -> Cbool a
or f g = f true g
t11 = or true true -- returns function true
t12 = or true false -- returns function true
t13 = or false true -- returns function true
t14 = or false false -- returns function false
t15 = true `or` true -- returns function true (note the use of infix
notation)
Let's get some more experience working with the 'Cbool a' type. Recall that the
'a' in 'Cbool a' can be any type, including 'Cbool Integer' so let's look at a
couple functions which use 'Cbool(Cbool Integer)'.
test2 takes one argument of type 'Cbool(Cbool Integer)' and it returns an
Integer:
test2 :: Cbool(Cbool Integer) -> Integer
test2 f = (f true false) 1 2
test2 uses its argument to choose between true and false. The result is then
applied to 1 2. If test2 is given true as its argument, then true is chosen,
which then selects 1. If test2 is given false as its argument, then false is
chosen, which then selects 2.
t16 = test2 true -- returns 1
t17 = test2 false -- returns 2
test3 takes one argument which is a 'Cbool(Cbool Integer)' and it returns a
'Cbool Integer':
test3 :: Cbool(Cbool Integer) -> Cbool Integer
test3 f = f true false
test3 chooses between true and false and returns the choice. If test3 is given
true as its argument, then true is returned. If test3 is given false as its
argument, then false is returned. Thus, test3 is an identity function for true
and false.
t18 = test3 true -- returns function true
t19 = t18 1 2 -- returns 1
We are finished with Church Booleans (Cbool). We now examine Church numbers
(Cnum).
---------------------
Church Numbers
---------------------
What are the natural numbers actually for? One might answer that they are for
controlling the number of times that 'some thing' is to be done.
We can capture this impression by defining the numbers as functions.
Let f denote the 'thing to be done'.
f is a function.
Numbers are used to control the number of times that f should be applied to its
arguments.
Each number behaves like this: when given some function f it returns the
appropriate number of applications of f.
'zero' means that f is to be applied no times.
Thus, zero f returns the identity (id) function
zero f = id
'one' means that f is to be applied once.
Thus, one f returns f
one f = f
'two' means that f is to be applied twice.
Thus, two f returns f . f
two f = f . f
And so forth.
So each number takes a function (a -> a) as its argument and returns a function
(a -> a):
zero, one, two :: (a -> a) -> (a -> a)
The returned function may then be applied to its arguments.
Here are some examples of using numbers:
Let f be this function: append the string "world"
f = (++ "world")
Let the argument to the returned function be: "Hello"
t20 = zero f -- returns id
t21 = t20 "Hello" -- returns "Hello"
t22 = one f -- returns f
t23 = t22 "Hello" -- returns "Helloworld"
t24 = two f -- returns f . f
t25 = t24 "Hello" -- returns "Helloworldworld"
We've seen what zero f does, what one f does, and what two f does. But what
does zero do, what does one do, and what does two do?
What is zero? one? two?
'zero' is a function that, given any function h, it ignores h and returns id.
We can express that using a Lambda (anonymous) function:
(\h -> id)
Let's take an example: apply that Lambda function to f
(\h -> id) f
= id
'one' is a function that, given any function h, it applies h once:
(\h -> h)
Let's take an example: apply that Lambda function to f
(\h -> h) f
= f
'two' is a function that, given any function h, it applies h twice:
(\h -> h . h)
Let's take an example: apply that Lambda function to f
(\h -> h . h) f
= f . f
-------------------------------
The Cnum Type Synonym
-------------------------------
Let's create a type synonym for (a -> a) -> (a -> a)
We call the type synonym Cnum
type Cnum a = (a -> a) -> (a -> a)
We've seen that zero, one, and two are Church numbers
zero :: Cnum a
one :: Cnum a
two :: Cnum a
test4 is a function that takes one argument which is a 'Cnum String' and it
returns a String
test4 :: Cnum String -> String
test4 cn = cn f "Hello"
test4 appends cn copies of "world" onto "Hello"
t26 = test4 zero -- returns "Hello"
t27 = test4 one -- returns "Helloworld"
t28 = test4 two -- returns "Helloworldworld"
Let's trace the evaluation of t28
t28 = test4 two
= two f "Hello"
= (f . f) "Hello"
= ((++ "world") . (++ "world")) "Hello"
= (++ "world") "Helloworld"
= "Helloworldworld"
----------------------------------------
Predecessor of a Church Number
----------------------------------------
Each Church number (except zero) can be defined in terms of its preceding
number. Thus two f can be defined using one
two f = f . one f
And one f can be defined using zero
one f = f . zero f
--------------------------------------
Successor of a Church Number
--------------------------------------
The successor of a Church number is defined by applying f one more time.
The successor of zero f is: f . zero f
The successor of one f is: f . one f
The successor of two f is: f . two f
Let's define a 'succ' function.
succ takes as input a Cnum and it returns the next Cnum. For example, succ zero
returns one.
So the successor of a Church number, cn, is a number such that when applied to
f, it applies f (cn + 1) times. This can be implemented using a Lambda
function:
succ :: Cnum a -> Cnum a
succ cn = (\h -> h . cn h)
t29 = succ zero -- returns (\h -> h . zero h)
-- (\h -> h . id)
t30 = t29 f "Hello" -- returns (\h -> h . id) f "Hello"
-- (f . id) "Hello"
-- "Helloworld"
t31 = succ one -- returns (\h -> h . one h)
-- (\h -> h . h)
t32 = t31 f "Hello" -- returns (\h -> h . h) f "Hello"
-- (f . f) "Hello"
-- "Helloworldworld"
t33 = succ two -- returns (\h -> h . two h)
-- (\h -> h . h . h)
t34 = t33 f "Hello" -- returns (\h -> h . h . h) f "Hello"
-- (f . f. f) "Hello"
--
"Helloworldworldworld"
--------------------------------------------------------------------------
Convert Natural Numbers to Church Numbers and Vice Versa
--------------------------------------------------------------------------
First we create a program that converts natural numbers into Church numbers.
The Church number for 0 is zero. The Church number for 'n' is the successor of
the Church number for (n - 1).
church :: Int -> Cnum Int
church 0 = zero
church n = succ (church (n-1))
g = (+1)
t35 = church 0 -- returns zero
t36 = t35 g -- returns id
t37 = t36 0 -- returns 0
t38 = church 1 -- returns one
t39 = t38 g -- returns g . id
t40 = t39 0 -- returns 1
t41 = church 2 -- returns two
t42 = t41 g -- returns g . g . id
t43 = t42 0 -- returns 2
t44 = church 5 -- return five
t45 = t44 g -- returns g . g . g . g . g . id
t46 = t45 0 -- returns 5
Next, we create a program that converts Church numbers into natural numbers.
For Church number, cn, the natural number is obtained by applying cn to (+1) 0.
natural :: Cnum Int -> Int
natural cn = cn (+1) 0
t47 = natural zero -- returns 0
t48 = natural one -- returns 1
t49 = natural two -- returns 2
t50 = natural (church 5) -- returns 5
-------------------------------------------------------------------------------------------
Arithmetic with Church Numbers - addition, multiplication, exponentiation
-------------------------------------------------------------------------------------------
We can perform arithmetic with Church numbers.
'plus cn1 cn2' means the 'thing to be done' is to be applied cn2 times and then
cn1 times.
plus :: Cnum a -> Cnum a -> Cnum a
plus cn1 cn2 = (\h -> (cn1 h) . (cn2 h))
t51 = plus two one -- returns three
t52 = t51 g 0 -- returns 3
Let's trace that example:
plus two one = (\h -> (two h) . (one h))
= (\h -> (h . h) . (h))
= (\h -> h . h . h) (+1) 0
= ((+1) . (+1) . (+1)) 0
= 3
Here's how to multiply two Church numbers:
times :: Cnum a -> Cnum a -> Cnum a
times cn1 cn2 = cn1 . cn2
Notice that multiplication involves composing the two Church numbers.
Composing cn1 and cn2 means that the 'thing to be done' is to be applied cn2
times and then for each of them apply the 'thing to be done' cn1 times.
t53 = times two two -- returns four
t54 = t53 g 0 -- returns 4
Let's trace that example:
times two two = (\h -> h . h) . (\h -> h . h)
= ((\h -> h . h) . (\h -> h . h)) g 0
= (\h -> h . h) (g . g) 0
= ((g . g) . (g . g)) 0
= 4
Here is a function for exponentiation of Church numbers:
exponentiation e m = e m
e = exponent, expressed as a Church number
m = mantissa, expressed as a Church number
Notice that exponentiation involves applying the first Church number to the
second Church number.
The exponent expands h some number of times. Suppose e is two:
(\h -> h . h)
Then, e is applied to m, which has expanded h some number of times. Suppose m
is three. Here is e applied to m:
(\h -> h . h) (\h -> h . h . h)
So m is repeated e times:
(\h -> h . h . h) . (\h -> h . h . h)
Thus, m is raised to the e power.
three :: Cnum a
three f = f . f . f
t55 = exponentiation two three -- returns three**two =
nine
t56 = t55 g 0 -- returns 9
Let's trace that example:
exponentiation two three
= (\h -> h . h) (\h -> h . h . h)
= (\h -> h . h . h) . (\h -> h . h . h)
= ((\h -> h . h . h) . (\h -> h . h . h)) g 0
= (\h -> h . h . h) (g . g . g) 0
= ((g . g . g) . (g . g . g) . (g . g . g)) 0
= 9
/Roger
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 54, Issue 25
*****************************************