A bit of a neophyte haskell question, but I came across this example in Haskell's tutorial examples. For "find the last element of a list" there are some obvious versions, like
last' [x] = x
last' (_:xs) = last' xs
But I can't make sense of an alternate version presented:
myLast' = foldr1 (const id)
So, in trying to make sense of what the application of the id function is doing, I tried in ghci:
const id 1 2 -> gives 2
This binds like this:
(const id) 1 2 -> gives 2
And not like this:
const (id 1) 2 -> gives 1
But I'm not making sense of this. (const id)
should translate to something like
`(\x y->x) (\x->x)`
Shouldn't this return a function that simply returns the id of its first element? Or, how is the function order making (const id) behave differently than const?
-
The definition of
const
isconst x = \_ -> x
Hence,
(const id)
is a function which takes one argument and always returnsid
andconst id 1 2 = (\_ -> id) 1 2 = id 2 = 2
The definition of
foldr1
isfoldr1 f [x] = x foldr1 f (x:xs) = f x (foldr1 f xs)
If we have
myLast' = foldr1 (const id)
then
myLast' [x] = foldr1 (const id) [x] {- definition of foldr1 -} = x
and
myLast' (x:xs) = foldr1 (const id) (x:xs) {- definition of foldr1 -} = (const id) x (foldr1 (const id) xs) {- definition of const -} = (\_ -> id) x (foldr1 (const id) xs) {- function application -} = id (foldr1 (const id) xs) {- definition of id -} = foldr1 (const id) xs {- definition of myLast' -} = myLast' xs
which agrees with the definition of
last'
.Steve B. : ahhh. Didn't make the connection of the const returning the function. Thanks for the explanation.J Cooper : This is a great explanation, and stepping through it I can see how it works. But is foldr1 (const id) really the idiomatic way to do a myLast function? The first example given seems way more clear...Chris Conway : I wouldn't say it's idiomatic... Haskell geeks enjoy working out how to express things in a "point-free" style, or purely in terms of folds. It becomes a kind of programming puzzle. The first version is much more clear. -
I rely heavily on
:t
when trying to understand Haskell. In this case:Prelude> :t const id const id :: b -> a -> a
might have helped you see what was going on.
Jay Conrod : To clarify, ":t" is a command you can use in GHCI to print the type of an expression.
0 comments:
Post a Comment