nanimonai
nanimonai

Reputation: 73

Why are flip and flip(:) different functions in Haskell?

Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c
Prelude> :t flip(:)
flip(:) :: [a] -> a -> [a]

I don't think (:) is a special syntactic sugar for flip. So what has it done to flip?

Upvotes: 1

Views: 609

Answers (2)

Will Ness
Will Ness

Reputation: 71109

flip (:) is an application of flip and (:).

Their types are

Prelude> :t flip
flip ::   (a ->  b  ->  c ) -> ( b  -> a ->  c )
Prelude> :t (:)
(:)  ::    a -> [a] -> [a]
Prelude> :t flip (:)
flip (:) ::                     [a] -> a -> [a]

flip just switches the two arguments to a function:

flip f y x = f x y

Thus

flip (:) xs x = (:) x xs = x : xs

Upvotes: 3

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477230

The "ingredients" are:

flip :: (a -> (b -> c)) -> (b -> (a -> c))
(:) :: d -> ([d] -> [d])

So here flip can take a function (of type a -> b -> c), and it basically converts it to a function of type b -> a -> c, where thus the "parameters" (technically speaking in Haskell a function has exactly one parameter) are "flipped".

If you write flip (:), you thus flip the (:) function. Since the (:) function has type d -> [d] -> [d], the result is [d] -> d -> [d].

We can however perform a more rigorous type inference. Since (:) is the parameter of a function application with flip, we know that the type of (:) should be the same as the type of the parameter of flip, so:

   a -> ( b  -> c  )
~  d -> ([d] -> [d])
-----------------------
a ~ d, b ~ [d], c ~ [d]

So we conclude that a ~ d (a and d are the same type), b ~ c ~ [d]. This thus means that the type of flip (:) is:

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

or when we perform the replacements to more specific types:

flip (:) :: [d] -> d -> [d]

Semantically flip (:) takes a list xs, and an element x, and returns a list where the element is prepended to the given list (so (x:xs)).

Upvotes: 6

Related Questions