I wonder whether there is a good name for functions with the following signature and implementation (Haskell-notation):
humble :: (a -> a -> b) -> a -> b
humble f x = f x x
It seems somehow related to fold1 (fold with no base case).
As has been mentioned by #4castle in the comments, the function you're looking for is join in Control.Monad. It's type is
join :: Monad m => m (m a) -> m a
The simple reader monad is (->) r,so if we set m ~ (->) r, we get
join :: (->) r ((->) r a) -> (->) r a
or, more concisely,
join :: (r -> r -> a) -> (r -> a)
which is what you want.
Related
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m a -> (a -> m b) -> m b
-- how do you use >=> to write bind?
I am absolutely so confused, I understand how both of these works but I cant even get started.
I tried all the following alternatives:
bind1 a b = (b a)
bind2 a b = (a >=> b)
bind3 a b = (b >=> a)
bind4 a b = (a b)
but every single attempt raises an error. Where can i possibly start on this question?
Since >>= has 2 parameters, and >=> has 3, how can I use >=> to write >>= when there is 1 less parameter?
First I'd suggest renaming the type parameters so the final result matches:
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m a -> (a -> m c) -> m c
Now we have a b -> m c in the first signature and a -> m c in the second; that suggests renaming also a to b:
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m b -> (b -> m c) -> m c
That leaves the main difference as having an extra argument a. But we evidently don't need that, so we might as well specialize it to the information-less type () (or any other single-value type):
(>=>) :: Monad m => (() -> m b) -> (b -> m c) -> (() -> m c)
bind :: Monad m => m b -> (b -> m c) -> m c
() -> m x is actually isomorphic to m x alone:
addDummyArg :: a -> (() -> a)
addDummyArg c () = c
rmDummyArg :: (() -> a) -> a
rmDummyArg f = f ()
And it's just a matter of using those conversion functions to adapt the functions to each other.
Since >>= has 2 parameters, and >=> has 3, how can I use >=> to write >>= when there is 1 less parameter?
Each function in Haskell has one parameter. You can interpret >=> , as a function that has as first parameter something of type a -> m b and the second something of b -> m c, the a -> m c is the "result" function.
What you here can do is manipulate the first parameter of bind into a function that accepts a parameter, and then provide that parameter, something like:
bind :: Monad m => m a -> (a -> m b) -> m b
bind ma f = (const ma >=> f) undefined
Here with const ma, we thus create a function that takes a parameter we do not care about, then we construct an a -> m c by using >=> and we call it with undefined (or some other value) to produce the m c value.
I have recently started learning Haskell, and I was trying to do the following function composition (join . mapM) but got some weird types out of this function that I don't understand. I thought that either GHC would assume that t == m in the mapM type and the output of mapM would become m (m b) which would be join-able or it would not and this would error out because of type mismatch. Instead the following happened:
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
join :: Monad m => m (m a) -> m a
join . mapM :: Traversable t => (a -> t a -> b) -> t a -> t b
I don't understand how this is possible. The way I understand it, function composition should use the inputs of the first (or the second depending how you look at it) function and the outputs of the second function. But here the expected input function for mapM changes from a unary function to a binary function and I have no clue why. Even if GHC can't just make the assumption that t == m like I did, which I half expected, it should error out because of type mismatch, not change the input function type, right? What is happening here?
First you specialize mapM to:
mapM' :: Traversable t => (a -> x -> b) -> t a -> x -> t b
(since (->) x is a monad)
Then you specialize it further to:
mapM'' :: Traversable t => (a -> t a -> b) -> t a -> t a -> t b
(we're just fixing the x to be t a)
Finally we specialize join appropriately:
join' :: (x -> x -> r) -> x -> r
(again, (->) x is a monad)
And hopefully it becomes more apparent why the composition join' . mapM'' is
join' . mapM'' :: Traversable t => (a -> t a -> b) -> t a -> t b
Maybe the following will be more illuminating, instead :
flip mapT :: (Traversable t, Monad m) => t a -> (a -> m b) -> t (m b)
sequenceA :: (Traversable t, Monad m) => t (m b) -> m (t b)
flip mapM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
flip liftM :: Monad m => m a -> (a -> m b) -> m (m b)
join :: Monad m => m (m b) -> m b
(join .) . flip liftM :: Monad m => m a -> (a -> m b) -> m b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(using some more specialized types than the most general ones, here and there; also with the renamed mapT f = runIdentity . traverse (Identity . f)).
Your specific question is less interesting. Type derivation is a fully mechanical process. Some entities must be compatible for the whole expression to make sense, so their types must unify:
(join . mapM) a_mb x = -- a_mb :: a -> m b
= join (mapM a_mb) x
= join ta_mtb x -- ta_mtb :: t a -> m (t b)
To join a function is to call it twice,
= ta_mtb x x
which means x is a t a and so m is t a ->:
x :: t a
ta_mtb :: t a -> m (t b)
----------------------------
ta_mtb x :: m (t b)
~ t a -> t b
x :: t a
----------------------------
ta_mtb x x :: t b
thus a_mb :: a -> m b ~ a -> t a -> b.
Working through the Haskell Book and my brain is breaking on the following example. I really don't know what the flip function is doing on line 21
1 class Functor f where
2 fmap :: (a -> b) -> f a -> f b
3
4 class Functor f => Applicative f where
5 pure :: a -> f a
6 (<*>) :: f (a -> b) -> f a -> f b
7
8 class Applicative f => Monad f where
9 return :: a -> f a
10 (>>=) :: f a -> (a -> f b) -> f b
11
12 instance Functor ((->) r) where
13 fmap = (.)
14
15 instance Applicative ((->) r) where
16 pure = const
17 f <*> a = \r -> f r (a r)
18
19 instance Monad ((->) r ) where
20 return = pure
21 ra >>= arb = flip arb <*> ra
-- flip :: (a -> b -> c) -> b -> a -> c
-- ra >>= arb = flip arb <*> ra
As I understand it, flip takes a function that takes two arguments, then two individual arguments, and returns a value. In the bind example, are we passing arb as the (a -> b -> c), then <*> as the b in flip's signature, and finally ra as the a? I can't see it.
I've tried making the types more specific to my actual example so you could rewrite <*> as
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
and I can do the same for bind
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
so even a dummy like myself can see that if we could swap <*> around
we could line then up like
(<???>) :: (r -> a) -> (r -> a -> b) -> (r -> b)
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
but looking at the second arguments there, the first one wants an r as its first argument and bind wants an a
So somehow flip is the book's example is doing that for us, but I really don't understand how. Any help would be greatly appreciated.
Thank you!
Top-level point of confusion, I think: flip is modifying arb, not modifying <*> as you seem to believe. We have "modified" <*> to have the "right" argument order just by giving <*> its arguments in the opposite order we got them!
Now for the details. We have, as you noted:
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
So, since we have on the left hand side written
ra >>= arb = ...
then what we have in scope is:
ra :: r -> a
arb :: a -> r -> b
(Note how the names were chosen to reflect the types!) Rewriting the type you gave for flip, we have
flip :: (a -> b -> c) -> b -> a -> c -- original
flip :: (a -> r -> b) -> r -> a -> b -- rename variables
hence:
flip arb :: r -> a -> b
Now recall the type of (<*>) that you wrote:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
So for the first argument to (<*>), we want something of type r -> a -> b. Hey! flip arb has that type! For the second argument, we want something of type r -> a. And we're in luck again, because ra has that type, so...
flip arb <*> ra :: r -> b
(As usual with infix operators, this is the application of the operator (<*>) the arguments flip arb and ra.) What type were we hoping to have? Well, we go back to the type of (>>=) now:
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
After taking two arguments, this is supposed to return something of type r -> b. Cool, that's what we have built.
ra >>= arb = flip arb <*> ra
I recently stumbled across Djinn and was briefly playing around with it to try to see whether it would be useful in my everyday coding workflow. I was excited to see that Djinn had monads and tried to see whether it might be able to find some cool functions.
Djinn did in fact work some wonders. The type signature of the initially (at least to me) unintuitive function >>= (>>=) is Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b. Djinn was able to immediately demystify this by stating
Djinn> f ? Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b
f :: (Monad m) => ((a -> m b) -> m a) -> (a -> m b) -> m b
f a b = a b >>= b
Unfortunately, Djinn can't seem to find other standard functions on monads, despite knowing about the Monad typeclass.
join (which should be join = (>>= id) or in Djinn's more verbose syntax join a = a >>= (\x -> x))
Djinn> join ? Monad m => m (m a) -> m a
-- join cannot be realized.
liftM (which should be liftM f = (>>= (return . f)) or in Djinn's more verbose syntax liftM a b = b >>= (\x -> return (a x)))
Djinn> liftM ? Monad m => (a -> b) -> m a -> m b
-- liftM cannot be realized.
Even the basic return :: Monad m => m a -> m (m a) cannot be found by Djinn or return :: Monad m => (a, b) -> m (a, b).
Djinn> f ? Monad m => (a, b) -> m (a, b)
-- f cannot be realized.
Djinn knows how to use \ to construct anonymous functions so why is this the case?
My rough suspicion is that perhaps Djinn has a simplistic notion of typeclass and somehow treats m a as "fixed" so that m (a, b) is not seen as a case of m a, but I have no idea how to make that any more concrete than its current hand-wavy form or whether that intuition is correct.
Supporting type classes properly looks a lot like supporting rank-2 types; compare:
join :: Monad m
=> m (m a) -> m a
vs:
join :: (forall a. a -> m a)
-> (forall a b. m a -> (a -> m b) -> m b)
-> m (m a) -> m a
Unfortunately, the techniques Djinn uses don't handle rank-2 types at all. If you float the foralls so that Djinn can process it, suddenly what you get instead are concrete choices:
join :: (b -> m b)
-> (m c -> (c -> m d) -> m d)
-> m (m a) -> m a
which looks a lot less like you could implement it! If you tell Djinn which instantiations to use, it does a lot better, of course.
join :: (b -> m b)
-> (m (m a) -> (m a -> m a) -> m a)
-> m (m a) -> m a
For this one, Djinn will give the right implementation. ...but then, that's cheating.
I have too functions:
higherOrderPure :: (a -> b) -> c
effectful :: Monad m => (a -> m b)
I'd like to apply the first function to the second:
higherOrderPure `someOp` effectful :: Monad m => m c
where
someOp :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
Example:
curve :: (Double -> Double) -> Dia Any
curve f = fromVertices $ map p2 [(x, f x) | x <- [1..100]]
func :: Double -> Either String Double
func _ = Left "Parse error" -- in other cases this func can be a useful arithmetic computation as a Right value
someOp :: ((Double -> Double) -> Dia Any) -> (Double -> Either String Double) -> Either String (Dia Any)
someOp = ???
curve `someOp` func :: Either String (Dia Any)
The type
Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
is not inhabited, i.e., there is no term t having that type (unless you exploit divergence, e.g. infinite recursion, error, undefined, etc.).
This means, unfortunately, that it is impossible to implement the operator someOp.
Proof
To prove that it is impossible to construct such a t, we proceed by contradiction.
Assume t exists with type
t :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
Now, specialize c to (a -> b). We obtain
t :: Monad m => ((a -> b) -> a -> b) -> (a -> m b) -> m (a -> b)
Hence
t id :: Monad m => (a -> m b) -> m (a -> b)
Then, specialize the monad m to the continuation monad (* -> r) -> r
t id :: (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r
Further specialize r to a
t id :: (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a
So, we obtain
t id const :: ((a -> b) -> a) -> a
Finally, by the Curry-Howard isomorphism, we deduce that the following is an intuitionistic tautology:
((A -> B) -> A) -> A
But the above is the well-known Peirce's law, which is not provable in intuitionistic logic. Hence we obtain a contradiction.
Conclusion
The above proves that t can not be implemented in a general way, i.e., working in any monad. In a specific monad this may still be possible.
I think you can achieve what you want by writing a monadic version of curve:
curveM :: Monad m => (Double -> m Double) -> m (QDiagram B R2 Any)
curveM f = do
let xs = [1..100]
ys <- mapM f xs
let pts = map p2 $ zip xs ys
return $ fromVertices pts
This can easily be written shorter, but it has the type you want. This is analogous to map -> mapM and zipWith -> zipWithM. The monadic versions of the functions have to be separated out into different implementations.
To test:
func1, func2 :: Double -> Either String Double
func1 x = if x < 1000 then Right x else Left "Too large"
func2 x = if x < 10 then Right x else Left "Too large"
> curveM func1
Right (_ :: QDiagram B R2 Any)
> curveM func2
Left "Too large"