How do I add the elements of two tuples in Haskell to give me a third tuple. The signature is something like,
Add :: (Int,Int) -> (Int,Int) ->(Int,Int)
Add a b = ....
So far, I am only able to think of this:
Add a b = [(x, y) | a = (x1, y1), b = (x2, y2), x=x1+x2, y =y1+y2n]
I am very new to Haskell however, so is what I am doing even correct?
What you are doing is not correct. List comprehensions are not the right way to do this.
Using pattern matching to extract the elements of the tuples:
add :: (Int, Int) -> (Int, Int) -> (Int, Int)
add (x, y) (u, v) = (x+u, y+v)
Extracting the elements of the tuples using fst and snd:
add2 :: (Int, Int) -> (Int, Int) -> (Int, Int)
add2 x y = (fst x + fst y, snd x + snd y)
Also keep in mind that functions can't start with capital letters in Haskell.
About your attempt, try running it in ghci and you'll see an error. As to why, that syntax you're trying to use is know as list comprehension, and it is documented here; it is syntactic surgar to create lists, such as [1,2,3], so it's not the right tool for you, as the ability to sum to pairs, which have type (·,·), not [·] (where by · I mean "any type").
Below is a non-basic (and probably overkill) way to write the function you want. But setting the target of understand it could be a way to force yourself going deeper in Haskell.
Here it is:
import Data.Bifunctor (bimap)
import Data.Tuple.Extra (both)
sumTwoTuples x y = uncurry bimap (both (+) x) y
How does this work? Let's see
> :t both
both :: (a -> b) -> (a, a) -> (b, b)
So both takes a function and applies it to both elements of a pair; therefore both (+) will apply (+) to both sides of the first pair x; if that's (3,4), you'll get ((3+), (4+)) (yeah, I'd write it as (3+,4+), but that's illegal syntax).
Now we have this pair of functions both (+) x, and we want to apply each of them to one side of the pair y.
Here's bimap:
> :t bimap
bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
So it takes 2 functions and applies it to each side of a Bifunctor (in our case the Bifunctor type p is (,)).
It's almost what we need, but it takes the two functions as two separate arguments, not a pair containing them.
uncurry gives a way to adjust that:
> :t uncurry
uncurry :: (a -> b -> c) -> (a, b) -> c
Indeed, uncurry bimap has this type:
> :t uncurry bimap
uncurry bimap :: Bifunctor p => (a -> b, c -> d) -> p a c -> p b d
so it takes a pair of functions and applies each to the corresponding side of the pair y, which has type p b d with p being (,) in our case.
The type of the finally produced value of your function starts with a ( but a list's type starts with a [. They can't match, so your approach can't be right. But we can mend it.
You are correct in trying to pattern match the values with the tuples of variables, but actually the patterns go to the left and values go to the right of the equal sign. And it must be inside a let:
add1 :: (Int,Int) -> (Int,Int) -> [(Int,Int)] -- NB: added brackets!
add1 a b = [(x, y) | let (x1, y1) = a ; (x2, y2) = b ;
x = x1 + x2 ; y = y1 + y2 ]
and actually we don't need that let inside the list comprehension,
add2 :: (Int,Int) -> (Int,Int) -> [(Int,Int)]
add2 a b = let { (x1, y1) = a ; (x2, y2) = b ;
x = x1 + x2 ; y = y1 + y2 } in
[(x, y)]
and now we can just get rid of those brackets, to get the value and the type which you wanted.
There's another, a bit tricky way to make your original code work without changing anything in it (except fixing the wrong capitalization of add and making it the proper let syntax of course).
We just add one word and enable one extension, and it works:
{-# LANGUAGE MonadComprehensions #-}
import Data.Function.Identity
add :: (Int,Int) -> (Int,Int) -> (Int,Int)
add a b = magicWord
[(x, y) | let { (x1, y1) = a ; (x2, y2) = b ;
x = x1 + x2 ; y = y1 + y2 } ]
The magic word is
magicWord = runIdentity
With that extension, the inferred type for the definition is
add :: (Num t1, Num t, Monad m)
=> (t, t1) -> (t, t1) -> m (t, t1)
and since
runIdentity :: Identity a -> a
using it forces m ~ Identity and it just works: the derived type is
(Num t1, Num t, Monad m)
=> (t, t1) -> (t, t1) -> m (t, t1)
Identity a -> a
--------------------------------------------
m ~ Identity , Monad Identity
(t,t1) ~ a
--------------------------------------------
(Num t1, Num t)
=> (t, t1) -> (t, t1) -> (t, t1)
which matches your given type signature
(Int, Int) -> (Int, Int) -> (Int, Int)
since Int is in Num,
and Identity is indeed a monad, one that does nothing at all,
newtype Identity a = Identity {runIdentity :: a}
fmap f (Identity a) = Identity (f a)
join (Identity (Identity a)) = Identity a
except tagging the values with its tag, which even disappears right away because the type Identity a is defined as newtype, not data.
Related
Suppose I have a type Pair:
data Pair a = Pair a a
What is the right way to write a monad instance for it? My idea is roughly this:
instance Semigroup a => Semigroup (Pair a) where
Pair a1 a2 <> Pair b1 b2 = Pair (a1 <> b1)(a2 <> b2)
instance Monad Pair where
return = pure
(Pair a b) >>= f = f a <> f b
Is it correct? If so then where to specify that b-type in the Pair b is a semigroup?
Actually, the only correct monad instance of Pair is as follows.
instance Monad Pair where
m >>= f = joinPair (f <$> m)
joinPair :: Pair (Pair a) -> Pair a
joinPair (Pair (Pair x _) (Pair _ y)) = Pair x y
The reason this is the correct monad instance is because Pair is a representable functor.
instance Representable Pair where
type Rep Pair = Bool
index (Pair x _) False = x
index (Pair _ y) True = y
tabulate f = Pair (f False) (f True)
Turns out, for every representable functor (>>=) is equivalent to the following bindRep function.
bindRep :: Representable f => f a -> (a -> f b) -> f b
bindRep m f = tabulate (\a -> index (f (index m a)) a)
If we specialize the bindRep function to Pair we get the following.
bindRep :: Pair a -> (a -> Pair b) -> Pair b
bindRep (Pair x y) f = tabulate (\a -> index (f (index (Pair x y) a)) a)
= Pair (index (f x) False) (index (f y) True)
-- |_________________| |________________|
-- | |
-- (1st elem of f x) (2nd elem of f y)
The following blog post by Adelbert Chang explains it better. Reasoning with representable functors.
Here's another way to prove uniqueness. Consider the left and right identity monad instance laws.
return a >>= k = k a -- left identity law
m >>= return = m -- right identity law
Now, for the Pair data type return x = Pair x x. Hence, we can specialize these laws.
Pair a a >>= k = k a -- left identity law
m >>= \x -> Pair x x = m -- right identity law
So, what should the definition of >>= be in order to satisfy these two laws?
Pair x y >>= f = Pair (oneOf [x1, x2, y1, y2]) (oneOf [x1, x2, y1, y2])
where Pair x1 y1 = f x
Pair x2 y2 = f y
The oneOf function returns one of the elements of the list non-deterministically.
Now, if our >>= function is to satisfy the left identity law then when x = y then x1 = x2 and y1 = y2 and the result must be Pair (oneOf [x1, x2]) (oneOf [y1, y2]).
Similarly, if our >>= function is to satisfy the right identity law then x1 = y1 = x and x2 = y2 = y and the result must be Pair (oneOf [x1, y1]) (oneOf [x2, y2]).
Hence, if you want to satisfy both laws then the only valid result is Pair x1 y2.
Functor and applicative instances are easy. The monad instance has taken a while to me.
data Pair a = Pair a a deriving (Eq, Show)
instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)
instance Applicative Pair where
pure a = Pair a a
(Pair f g) <*> (Pair a b) = Pair (f a) (g b)
instance Monad Pair where
return = pure
(Pair a b) >>= f = let Pair a' _ = f a
Pair _ b' = f b
in Pair a' b'
The way I've come to this solution is by applying the monad laws. Easily you can check with an example that identity law doesn't hold if you take Pair a' a'' or Pair b' b'' or Pair a' b' nor Pair a'' b''. So the only solutions must be in the diagonals. Defining
(m >>= f) = Pair (first . f . first $ m) (second . f . second $ m)
where first and second are the obvious ones, you can proof all of the laws.
It is possible to make Pair into Monad by having join that takes the diagonal.of the 2×2 square. return has no other choice but replicate its argument. This turns Pair into essentially a fixed length ZipList.
Of course this definition of join discards some data. This may or may not be important.
A Monad instance may not place any constraints on the type of data it contains (the a here). It must treat that data as fully opaque. I don't think your Pair type admits a Monad instance (or Applicative), because there is no way to turn a pair of pairs into a single pair without either losing some of the data, or using it in some way not permitted by the typeclass definition.
Why I am answering
I was curious to know what the practical usages of the Pair a monad are, especially considering that the only valid implementation of (>>=) actually throws away half of the data, so I asked this question.
It turns out that the answer I accepted is a very interesting answer to this question too (and was contained in Daniel Wagner's comment under the present question, but I hadn't noticed it), so I will elaborate it a bit here, because I've learned a lot from it.
The short answer: (a,a) and Bool -> a are the same thing
So the short answer is that the types Pair a, or more simply (a,a), and Bool -> a are isomorphic: feeding a (a,a) to fst/snd is equivalent to feeding a Bool -> a function with True/False (or False/True, it's just a choice). The two isomorphisms are actually shown in the (deleted) answer from Zhiltsoff Igor:
funToPair :: (Bool -> a) -> (a, a)
funToPair f = (f True, f False)
pairToFun :: (a, a) -> Bool -> a
pairToFun (x, y) True = x
pairToFun (x, y) False = y
As a consquence, whichever way Bool -> a is a monad, (a,a)/Pair a is a monad in the same way.
But (a,a)'s Monad throws information away... so does Bool -> a!
What bugged me at this point was that it's so apparent that the Monad instance for (a,a)/Pair a, thoroughly explained in Aadit M Shah's answer, throws away data, whereas the Monad instance for Bool -> a... doesn't...?
Fatally wrong! The Monad instance for r -> a (with generic r, not just Bool) throws away information all the time! How? Let's look at the well known implementation of >>=:
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
Now remember that a function of type x -> y is equivalent to a tuple of type (y,y,...,y) with as many entries as the number of possible values of type x (not y).
What about k? k is a binary function, let's say of type x -> y -> z, so it can be fed with the cartesian product of the values that inhabit the type x and those that inhabit the type of y. If x and y are inhabited by m and n values respectively, then k is equivalent to a tuple of type (z,z,...,z) with as many entries as m*n, and that is the information that comes with k.
Now the question is whether (>>=) makes use of all that information. No, it doesn't! (>>=) is feeding k with only n possible inputs: the second argument r is any value of type x, whereas the first argument is the single value corresponding to r via f.
If we think of mathematical functions, we are saying that, for fixed unary function f: A → B and binary function k: B×A → C, f >>= k is the unary function that does t ∈ A → k(f(t),t) ∈ C, i.e. it's a restriction of k to the curve parametrized by the equations x = f(t) and y = t.
Going back to Bool -> a, the signature of (>>=) specilizes to
(>>=) :: (Bool -> a) -> (a -> Bool -> b) -> Bool -> b
f >>= k = \r -> k (f r) r
which we can rewrite as follows, just to make the obvious more apparent:
(>>=) f k r
| r == True = k (f True) True
| r == False = k (f False) False
-- remember this
What's obvious in the above? If we feed f >>= k with True, we'll only use f True, thus throwing away the other half of the data, f False. Similarly, if we call (f >>= k) False, we throw away whatever f True is. This way of throwing away half of the information contained in k mirrors exactly what is throw away via the _ placeholders for (a,a) aka Pair a (adaptation from Ismor's answer):
instance Monad Pair where
return = pure
(Pair a b) >>= k = let Pair a' _ = k a
Pair _ b' = k b
in Pair a' b'
Indeed, if we define fst' (Pair a _) = a and snd' (Pair _ b) = b (these are mirroring fst and snd for (,)), then (>>=) can be written simply as follows
(>>=) :: Pair a -> (a -> Pair b) -> Pair b
p >>= k = (fst' (k (fst' p)),
snd' (k (snd' p)))
Which is in my opinion strikingly similar to the code I marked with -- remember this, with fst' mirrors True and snd' mirrors False.
By the way, for the following, let's take note of the type of (>>=) in the case we were allowed to write it for (a,a):
(>>=) :: (a,a) -> (a -> (b,b)) -> (b,b)
What about (a,b) when a and b are the same type?
This was the last doubt I had: since (a,b) is a Monad in b provided a is a Monoid, in the special case that the type b is equal to the type a (and b has to be a Monoid), do we get the same instance as above?
No, the question above is ill-posed, the flaw being in the part "in the special case that the type b is equal to the type a". This hypothesis is simply not possible because for a type constructor to be a Monad, it has to have one and only one free type parameter:
(a,b) is made a Monad in the free parameter b, meaning that b will be allowed to vary according to the second argument to (>>=), whereas the type a will stay the same through the (>>=) operator;
(a,a) is made a Monad in the free parameter a, meaning that a will be allowed to vary according to the second argument to (>>=), whereas... nothing, that's it, all explained in the previous part of the answer.
I've been using the Free datatype in Control.Monad.Free from the free package. Now I'm trying to convert it to use F in Control.Monad.Free.Church but can't figure out how to map the functions.
For example, a simple pattern matching function using Free would look like this -
-- Pattern match Free
matchFree
:: (a -> r)
-> (f (Free f a) -> r)
-> Free f a
-> r
matchFree kp _ (Pure a) = kp a
matchFree _ kf (Free f) = kf f
I can easily convert it to a function that uses F by converting to/from Free -
-- Pattern match F (using toF and fromF)
matchF
:: Functor f
=> (a -> r)
-> (f (F f a) -> r)
-> F f a
-> r
matchF kp kf = matchF' . fromF
where
matchF' (Pure a) = kp a
matchF' (Free f) = kf (fmap toF f)
However I can't figure out how to get it done without using toF and fromF -
-- Pattern match F (without using toF)???
-- Doesn't compile
matchF
:: Functor f
=> (a -> r)
-> (f (F f a) -> r)
-> F f a
-> r
matchF kp kf f = f kp kf
There must be a general pattern I am missing. Can you help me figure it out?
You asked for the "general pattern you are missing". Let me give my own attempt at explaining it, though Petr Pudlák's answer is also pretty good. As user3237465 says, there are two encodings that we can use, Church and Scott, and you're using Scott rather than Church. So here's the general review.
How encodings work
By continuation passing, we can describe any value of type x by some unique function of type
data Identity x = Id { runId :: x }
{- ~ - equivalent to - ~ -}
newtype IdentityFn x = IdFn { runIdFn :: forall z. (x -> z) -> z }
The "forall" here is very important, it says that this type leaves z as an unspecified parameter. The bijection is that Id . ($ id) . runIdFn goes from IdentityFn to Identity while IdFn . flip ($) . runId goes the other way. The equivalence comes because there is essentially nothing one can do with the type forall z. z, no manipulations are sufficiently universal. We can equivalently state that newtype UnitFn = UnitFn { runUnitFn :: forall z. z -> z } has only one element, namely UnitFn id, which means that it corresponds to the unit type data Unit = Unit in a similar way.
Now the currying observation that (x, y) -> z is isomorphic to x -> y -> z is the tip of a continuation-passing iceberg which allows us to represent data structures in terms of pure functions, with no data structures, because clearly the type Identity (x, y) is equivalent therefore to forall z. (x -> y -> z) -> z. So "gluing" together two items is the same as creating a value of this type, which just uses pure functions as "glue".
To see this equivalence, we have to just handle two other properties.
The first is sum-type constructors, in the form of Either x y -> z. See, Either x y -> z is isomorphic to
newtype EitherFn x y = EitherFn { runEitherFn :: forall z. (x -> z) -> (y -> z) -> z }
from which we get the basic idea of the pattern:
Take a fresh type variable z that does not appear in the body of the expression.
For each constructor of the data type, create a function-type which takes all of its type-arguments as parameters, and returns a z. Call these "handlers" corresponding to the constructors. So the handler for (x, y) is (x, y) -> z which we curry to x -> y -> z, and the handlers for Left x | Right y are x -> z and y -> z. If there are no parameters, you can just take a value z as your function rather than the more cumbersome () -> z.
Take all of those handlers as parameters to an expression forall z. Handler1 -> Handler2 -> ... -> HandlerN -> z.
One half of the isomorphism is basically just to hand the constructors in as the desired handlers; the other pattern-matches on the constructors and applies the correponding handlers.
Subtle missing things
Again, it's fun to apply these rules to various things; for example as I noted above, if you apply this to data Unit = Unit you find that any unit type is the identity function forall z. z -> z, and if you apply this to data Bool = False | True you find the logic functions forall z. z -> z -> z where false = const while true = const id. But if you do play with it you will notice that something's missing still. Hint: if we look at
data List x = Nil | Cons x (List x)
we see that the pattern should look like:
data ListFn x = ListFn { runListFn :: forall z. z -> (x -> ??? -> z) -> z }
for some ???. The above rules don't pin down what goes there.
There are two good options: either we use the power of the newtype to its fullest to put ListFn x there (the "Scott" encoding), or we can preemptively reduce it with the functions we've been given, in which case it becomes a z using the functions that we already have (the "Church" encoding). Now since the recursion is already being performed for us up-front, the Church encoding is only perfectly equivalent for finite data structures; the Scott encoding can handle infinite lists and such. It can also be hard to understand how to encode mutual recursion in the Church form whereas the Scott form is usually a little more straightforward.
Anyway, the Church encoding is a little harder to think about, but a little more magical because we get to approach it with wishful thinking: "assume that this z is already whatever you're trying to accomplish with tail list, then combine it with head list in the appropriate way." And this wishful thinking is precisely why people have trouble understanding foldr, as the one side of this bijection is precisely the foldr of the list.
There are some other problems like "what if, like Int or Integer, the number of constructors is big or infinite?". The answer to this particular question is to use the functions
data IntFn = IntFn { runIntFn :: forall z. (z -> z) -> z -> z }
What is this, you ask? Well, a smart person (Church) has worked out that this is a way to represent integers as the repetition of composition:
zero f x = x
one f x = f x
two f x = f (f x)
{- ~ - increment an `n` to `n + 1` - ~ -}
succ n f = f . n f
Actually on this account m . n is the product of the two. But I mention this because it is not too hard to insert a () and flip arguments around to find that this is actually forall z. z -> (() -> z -> z) -> z which is the list type [()], with values given by length and addition given by ++ and multiplication given by >>.
For greater efficiency, you might Church-encode data PosNeg x = Neg x | Zero | Pos x and use the Church encoding (keeping it finite!) of [Bool] to form the Church encoding of PosNeg [Bool] where each [Bool] implicitly ends with an unstated True at its most-significant bit at the end, so that [Bool] represents the numbers from +1 to infinity.
An extended example: BinLeaf / BL
One more nontrivial example, we might think about the binary tree which stores all of its information in leaves, but also contains annotations on the internal nodes: data BinLeaf a x = Leaf x | Bin a (BinLeaf a x) (BinLeaf a x). Following the recipe for Church encoding we do:
newtype BL a x = BL { runBL :: forall z. (x -> z) -> (a -> z -> z -> z) -> z}
Now instead of Bin "Hello" (Leaf 3) (Bin "What's up?" (Leaf 4) (Leaf 5) we construct instances in lowercase:
BL $ \leaf bin -> bin "Hello" (leaf 3) (bin "What's up?" (leaf 4) (leaf 5)
The isomorphism is thus very easy one way: binleafFromBL f = runBL f Leaf Bin. The other side has a case dispatch, but is not too bad.
What about recursive algorithms on the recursive data? This is where it gets magical: foldr and runBL of Church encoding have both run whatever our functions were on the subtrees before we get to the trees themselves. Suppose for example that we want to emulate this function:
sumAnnotate :: (Num n) => BinLeaf a n -> BinLeaf (n, a) n
sumAnnotate (Leaf n) = Leaf n
sumAnnotate (Bin a x y) = Bin (getn x' + getn y', a) x' y'
where x' = sumAnnotate x
y' = sumAnnotate y
getn (Leaf n) = n
getn (Bin (n, _) _ _) = n
What do we have to do?
-- pseudo-constructors for BL a x.
makeLeaf :: x -> BL a x
makeLeaf x = BL $ \leaf _ -> leaf x
makeBin :: a -> BL a x -> BL a x -> BL a x
makeBin a l r = BL $ \leaf bin -> bin a (runBL l leaf bin) (runBL r leaf bin)
-- actual function
sumAnnotate' :: (Num n) => BL a n -> BL n n
sumAnnotate' f = runBL f makeLeaf (\a x y -> makeBin (getn x + getn y, a) x y) where
getn t = runBL t id (\n _ _ -> n)
We pass in a function \a x y -> ... :: (Num n) => a -> BL (n, a) n -> BL (n, a) n -> BL (n, a) n. Notice that the two "arguments" are of the same type as the "output" here. With Church encoding, we have to program as if we've already succeeded -- a discipline called "wishful thinking".
The Church encoding for the Free monad
The Free monad has normal form
data Free f x = Pure x | Roll f (Free f x)
and our Church encoding procedure says that this becomes:
newtype Fr f x = Fr {runFr :: forall z. (x -> z) -> (f z -> z) -> z}
Your function
matchFree p _ (Pure x) = p x
matchFree _ f (Free x) = f x
becomes simply
matchFree' p f fr = runFr fr p f
Let me describe the difference for a simpler scenario - lists. Let's focus on how one can consume lists:
By a catamorphism, which essentially means that we can express it using
foldr :: (a -> r -> r) -> r -> [a] -> r
As we can see, the folding functions never get hold of the list tail, only its processed value.
By pattern matching we can do somewhat more, in particular we can construct a generalized fold of type
foldrGen :: (a -> [a] -> r) -> r -> [a] -> r
It's easy to see that one can express foldr using foldrGen. However, as foldrGen isn't recursive, this expression involves recursion.
To generalize both concepts, we can introduce
foldrPara :: (a -> ([a], r) -> r) -> r -> [a] -> r
which gives the consuming function even more power: Both the reduced value of the tail, as well as the tail itself. Clearly this is more generic than both previous ones. This corresponds to a paramorphism which “eats its argument and keeps it too”.
But it's also possible to do it the other way round. Even though paramorphisms are more general, they can be expressed using catamorphisms (at some overhead cost) by re-creating the original structure on the way:
foldrPara :: (a -> ([a], r) -> r) -> r -> [a] -> r
foldrPara f z = snd . foldr f' ([], z)
where
f' x t#(xs, r) = (x : xs, f x t)
Now Church-encoded data structures encode the catamorphism pattern, for lists it's everything that can be constructed using foldr:
newtype List a = L (forall r . r -> (a -> r -> r) -> r)
nil :: List a
nil = L $ \n _ -> n
cons :: a -> List a -> List a
cons x (L xs) = L $ \n c -> c x (xs n c)
fromL :: List a -> [a]
fromL (L f) = f [] (:)
toL :: [a] -> List a
toL xs = L (\n c -> foldr c n xs)
In order to see the sub-lists, we have take the same approach: re-create them on the way:
foldrParaL :: (a -> (List a, r) -> r) -> r -> List a -> r
foldrParaL f z (L l) = snd $ l (nil, z) f'
where
f' x t#(xs, r) = (x `cons` xs, f x t)
This applies generally to Church-encoded data structures, like to the encoded free monad. They express catamorphisms, that is folding without seeing the parts of the structure, only with the recursive results. To get hold of sub-structures during the process, we need to recreate them on the way.
Your
matchF
:: Functor f
=> (a -> r)
-> (f (F f a) -> r)
-> F f a
-> r
looks like the Scott-encoded Free monad. The Church-encoded version is just
matchF
:: Functor f
=> (a -> r)
-> (f r -> r)
-> F f a
-> r
matchF kp kf f = runF f kp kf
Here are Church- and Scott-encoded lists for comparison:
newtype Church a = Church { runChurch :: forall r. (a -> r -> r) -> r -> r }
newtype Scott a = Scott { runScott :: forall r. (a -> Scott a -> r) -> r -> r }
It's a bit of a nasty one. This problem is a more general version of a puzzle everyone struggles with the first time they're exposed to it: defining the predecessor of a natural number encoded as a Church numeral (think: Nat ~ Free Id ()).
I've split my module into a lot of intermediate definitions to highlight the solution's structure. I've also uploaded a self-contained gist for ease of use.
I start with nothing exciting: redefining F given that I don't have this package installed at the moment.
{-# LANGUAGE Rank2Types #-}
module MatchFree where
newtype F f a = F { runF :: forall r. (a -> r) -> (f r -> r) -> r }
Now, even before considering pattern-matching, we can start by defining the counterpart of the usual datatype's constructors:
pureF :: a -> F f a
pureF a = F $ const . ($ a)
freeF :: Functor f => f (F f a) -> F f a
freeF f = F $ \ pr fr -> fr $ fmap (\ inner -> runF inner pr fr) f
Next, I'm introducing two types: Open and Close. Close is simply the F type but Open corresponds to having observed the content of an element of F f a: it's Either a pure a or an f (F f a).
type Open f a = Either a (f (F f a))
type Close f a = F f a
As hinted by my hand-wavy description, these two types are actually equivalent and we can indeed write functions converting back and forth between them:
close :: Functor f => Open f a -> Close f a
close = either pureF freeF
open :: Functor f => Close f a -> Open f a
open f = runF f Left (Right . fmap close)
Now, we can come back to your problem and the course of action should be pretty clear: open the F f a and then apply either kp or kf depending on what we got. And it indeed works:
matchF
:: Functor f
=> (a -> r)
-> (f (F f a) -> r)
-> F f a
-> r
matchF kp kf = either kp kf . open
Coming back to the original comment about natural numbers: predecessor implemented using Church numeral is linear in the size of the natural number when we could reasonably expect a simple case analysis to be constant time. Well, just like for natural numbers, this case analysis is pretty expensive because, as show by the use of runF in the definition of open, the whole structure is traversed.
I was reviewing some code and came across the following gem, which I'd wager is a copy-paste of pointfree output:
(I thought the following would more appropriate than the usual foo/bar for this particular question :P)
import Control.Monad (liftM2)
data Battleship = Battleship { x :: Int
, y :: Int
} deriving Show
placeBattleship :: Int -> Int -> Battleship
placeBattleship x' y' = Battleship { x = x', y = y' }
coordinates :: Battleship -> (Int, Int)
coordinates = liftM2 (,) x y
Would someone be kind enough to explain the steps needed to simplify from: (i) coordinates b = (x b, y b) to: (ii) coordinates = liftM2 (,) x y? In particular, I'm a bit confused as to the use of liftM2 as I wasn't even aware that a monad was lurking in the background.
I know that (i) can also be represented as: coordinates s = (,) (x s) (y s) but I'm not sure where/how to proceed.
P.S. The following is why I suspect it's from pointfree (output is from GHCI and :pl is aliased to pointfree):
λ: :pl coordinates s = (x s, y s)
coordinates = liftM2 (,) x y
This takes advantage of the Monad instance for (->) r, also called the "reader monad". This is the monad of functions from a specific type to a. (Take a look here for motivation on why it exists in the first place.)
To see how it works for various functions, replace m with (r -> in m a. For example, if we just do liftM, we get:
liftM :: (a -> b) -> (m a -> m b)
liftM :: (a -> b) -> ((r -> a) -> (r -> b))
:: (a -> b) -> (r -> a) -> (r -> b) -- simplify parentheses
...which is just function composition. Neat.
We can do the same thing for liftM2:
liftM2 :: (a -> b -> c) -> m a -> m b -> m c
liftM2 :: (a -> b -> c) -> (r -> a) -> (r -> b) -> (r -> c)
So what we see is a way to compose two one-argument functions with a two-argument function. It's a way of generalizing normal function composition to more than one argument. The idea is that we create a function that takes a single r by passing that through both of the one-argument functions, getting two arguments to pass into the two-argument function. So if we have f :: (r -> a), g :: (r -> b) and h :: (a -> b -> c), we produce:
\ r -> h (f r) (h r)
Now, how does this apply to your code? (,) is the two-argument function, and x and y are one-argument functions of the type Battleship -> Int (because that's how field accessors work). With this in mind:
liftM2 (,) x y = \ r -> (,) (x r) (y r)
= \ r -> (x r, y r)
Once you've internalized the idea of multiple function composition like this, point-free code like this becomes quite a bit more readable—no need to use the pointfree tool! In this case, I think the non-pointfree version is still better, but the pointfree one isn't terrible itself.
The monad liftM2 is working over here is the function monad (->) a. This is equivalent to the Reader monad, as you may have seen before.
Recall the definition of liftM2:
liftM2 :: Monad m => (a -> b -> r) -> m a -> m b -> m r
liftM2 f ma mb = do
a <- ma
b <- mb
return $ f a b
So now if we substitute in (,) for f, x for ma, and y for mb, we get
liftM2 (,) x y = do
a <- x
b <- y
return $ (,) a b
Since x, y :: Battleship -> Int which is equivalent to ((->) Battleship) Int, then m ~ (->) Battleship. The function monad is defined as
instance Monad ((->) a) where
return x = const x
m >>= f = \a -> f (m a) a
Essentially what the function monad does is allow you to extract the output from several functions provided they all have the same input. A more clear example might be something like
test = do
a <- (^2)
b <- (^3)
c <- (^4)
d <- show
return (a, b, c, d)
> test 2
(4, 8, 16, "2")
You could easily rewrite
data Battleship = Battleship { x :: Int
, y :: Int
} deriving Show
placeBattleship :: Int -> Int -> Battleship
placeBattleship x y = Battleship x y
coordinates :: Battleship -> (Int, Int)
coordinates (Battleship x y) = (x, y)
It isn't point-free style, but quite simple
I'm pretty new to Haskell, so I hope this isn't a stupid question. I have this data type:
data N = I Int | D Double deriving (Show, Eq)
I'm trying to write a function with the signature (Num a) => (a -> a -> a) -> N -> N -> N which applies the function to the numbers within the Ns and returns an N with the result. If the Ns are both Ds, it should just apply the function and return a D; if one is an I and the other is a D, it should convert the Int in the I to a Double, apply the function to the two Doubles, and return a D; and if both are Is, it should apply the function and return an I. Here's the (broken) code I have so far:
widen :: N -> N -> (N, N)
widen (I i) d#(D _) = (D (fromIntegral i), d)
widen d#(D _) i#(I _) = widen i d
widen x y = (x, y)
numOp :: (Num a) => (a -> a -> a) -> N -> N -> N
numOp op x y = case widen x y of (D x', D y') -> D $ x' `op` y'
(I x', I y') -> I $ x' `op` y'
I get an error on both lines of numOp, though. The first one is:
Could not deduce (a ~ Double)
from the context (Num a)
bound by the type signature for
numOp :: Num a => (a -> a -> a) -> N -> N -> N
at <line num>
In the second argument of `($)', namely x' `op` y'
In the expression: D $ x' `op` y'
In a case alternative: (D x', D y') -> D $ x' `op` y'
And the second:
Couldn't match type `Double' with `Int'
Expected type: Int
Actual type: a
In the second argument of `($), namely x' `op` y'
In the expression: I $ x' `op` y'
In a case alternative: (I x', I y') -> I $ x' `op` y'
I'm pretty sure I understand what both errors mean; I think the first one is saying that the information in my type signature isn't enough for GHC to assume that op returns a Double, which is required by the D value constructor, and the second one is saying that since the first line implies that a is Double, this line can't use a value of type a as though it's an Int. I don't have any idea where to start looking for the right way to do this, though.
If it helps, the reason I'm trying to get this to work is that I'm following along with the Write Yourself a Scheme tutorial; all the examples in the tutorial (specifically in the Evaluation section) only deal with integers, but as an exercise I'd like to add the ability to support both integral and floating point numbers so that e.g. (+ 1 2.5 2.5) returns 6.0 and (+ 1 2 3) returns 6. If I'm thinking about this the wrong way or there's an easier way to accomplish it, I'd love to hear suggestions.
The signature
numOp :: (Num a) => (a -> a -> a) -> N -> N -> N
says that numOp takes any monomorphic function of type a -> a -> a for every specific instance of Num and two Ns and from that computes an N. So for example, a function of type
Complex Float -> Complex Float -> Complex Float
or
approxRational :: RealFrac a => a -> a -> Rational
(specialised to a = Rational) would be legitimate first arguments.
What you need is a polymorphic function that can handle all Num instances as the first argument, i.e. the rank 2 type
numOp :: (forall a. Num a => a -> a -> a) -> N -> N -> N
(you need the RankNTypes language extension for that).
Is there any type-safe way to write a function
bi f a b = (f a, f b)
such that it would be possible to use it like this:
x1 :: (Integer, Char)
x1 = bi head [2,3] "45"
x2 :: (Integer, Char)
x2 = bi fst (2,'3') ('4',5)
x3 :: (Integer, Double)
x3 = bi (1+) 2 3.45
?
In rank-n-types examples there are always something much simpler like
g :: (forall a. a -> a) -> a -> a -> (a, a)
g f a b = (f a, f b)
{-# LANGUAGE TemplateHaskell #-}
bi f = [| \a b -> ($f a, $f b)|]
ghci> :set -XTemplateHaskell
ghci> $(bi [|head|]) [2,3] "45"
(2,'4')
;)
Yes, though not in Haskell. But the higher-order polymorphic lambda calculus (aka System F-omega) is more general:
bi : forall m n a b. (forall a. m a -> n a) -> m a -> m b -> (n a, n b)
bi {m} {n} {a} {b} f x y = (f {a} x, f {b} y)
x1 : (Integer, Char)
x1 = bi {\a. List a} {\a. a} {Integer} {Char} head [2,3] "45"
x2 : (Integer, Char)
x2 = bi {\a . exists b. (a, b)} {\a. a} {Integer} {Char} (\{a}. \p. unpack<b,x>=p in fst {a} {b} x) (pack<Char, (2,'3')>) (pack<Integer, ('4',5)>)
x3 : (Integer, Double)
x3 = bi {\a. a} {\a. a} {Integer} {Double} (1+) 2 3.45
Here, I write f {T} for explicit type application and assume a library typed respectively. Something like \a. a is a type-level lambda. The x2 example is more intricate, because it also needs existential types to locally "forget" the other bit of polymorphism in the arguments.
You can actually simulate this in Haskell by defining a newtype or datatype for every different m or n you instantiate with, and pass appropriately wrapped functions f that add and remove constructors accordingly. But obviously, that's no fun at all.
Edit: I should point out that this still isn't a fully general solution. For example, I can't see how you could type
swap (x,y) = (y,x)
x4 = bi swap (3, "hi") (True, 3.1)
even in System F-omega. The problem is that the swap function is more polymorphic than bi allows, and unlike with x2, the other polymorphic dimension is not forgotten in the result, so the existential trick does not work. It seems that you would need kind polymorphism to allow that one (so that the argument to bi can be polymorphic over a varying number of types).
Even with ConstraintKinds, I think the barrier is going to be quantifying over the "type function" from the arguments to the results. What you want is for f to map a -> b and c -> d, and to take a -> b -> (c, d), but I don't think there's any way to quantify over that relationship with full generality.
Some special cases might be doable, though:
(forall x . cxt x => x -> f x) -> a -> b -> (f a, f b)
-- e.g. return
(forall x . cxt x => f x -> x) -> f a -> f b -> (a, b)
-- e.g. snd
(forall x . cxt x => x -> x) -> a -> b -> (a, b)
-- e.g. (+1)
but given that you're trying to quantify over more or less arbitrary type functions, I'm not sure you can make that work.
This is about as close as you're going to get, I think:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
module Data.Function.Bi (bi, Fn(..))
bi :: (Fn i a a', Fn i b b') => i -> a -> b -> (a', b')
bi i a b = (fn i a, fn i b)
class Fn i x x' | i x -> x' where
fn :: i -> x -> x'
Use it like so:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, RankNTypes,
FlexibleInstances, UndecidableInstances #-}
import Data.Function.Bi
data Snd = Snd
instance Fn Snd (a, b) b where
fn Snd = snd
myExpr1 :: (Int, String)
myExpr1 = bi Snd (1, 2) ("a", "b")
-- myExpr == (2, "b")
data Plus = Plus (forall a. (Num a) => a)
instance (Num a) => Fn Plus a a where
fn (Plus n) = (+n)
myExpr2 :: (Int, Double)
myExpr2 = bi (Plus 1) (1, 2) (1.3, 5.7)
-- myExpr2 == (3, 6.7)
It's very clunky, but as general as possible.