Reputation: 21063
I came across a Haskell function that tells whether a list is sorted, and I'm having trouble understanding how it works.
The code in question is
f = zipWith (<=) <*> tail
which I understand to be equivalent (in point-ful style) to
f' xs = zipWith (<=) xs (tail xs)
and as an example returns
f [4, 5, 1] == [True,False]
I take it that it has something to do with the list monad and sequential application, but would appreciate if someone could make the meaning more clear to me. What exactly is <*>
doing here?
Upvotes: 6
Views: 160
Reputation: 5406
<*>
is actually from (->) a
as Applicative Functor. It is a S-combinator which distributes the argument (list xs
in your expansion) to two functions (zipWith (<=)
and tail
) in the manner that you specified in the expansion: (f <*> g) x = f x (g x)
.
To understand this, you need to check the type (<*>)
is applied to. Since both of its arguments are a->b
, we are talking about a->b
as Applicative Functor - not List.
Upvotes: 7
Reputation: 53881
The <*>
here isn't acting on the [a]
applicative, it's acting in the (->) a
applicative instance.
Essentially
instance Applicative ((->) a) where
pure = const -- same as monadic return
f <*> a = \x -> f x (a x)
So it acts like function application, but also wraps the application in a function and gives the argument to both sides.
So expanding your function
zipWith (<=) <*> tail
\x -> zipWith (<=) x (tail x)
\(x:xs) -> zipWith (<=) (x:xs) xs
In general it's correct to view <*>
as just function application + some extra goodies. You can almost read it as whitespace!
Upvotes: 12