Do monads not guarantee the applicability of layered/non-layered monadic values to non-layered/non-monadic functions, and is this a good/bad thing? - monads

I'm just trying to get monads, so bear with me if I ask a bad question, but...
If monads only require:
(a -> M a), where M is the monadic type constructor, and
(M a -> (a -> M b) -> M b), which is the bind operation (which I understand as mapping a monad onto a non-monadic to monadic value function)
...doesn't this mean that:
(M a -> a) and
(M (M a) -> M a) are not implicitly required?
Won't this usually cause a problem?
Suppose we have a set of functions, S, which all have the type (x -> y), where x and y are arbitrary types.
Now, suppose I program using a set of monadic functions M, where their types are x -> M y.
Doesn't this mean that once I turn a type into M y, I can't use any of the (x -> y) functions? Or, can I assume that I can do (M x -> (x -> y) -> (y -> M y) -> M y)?
Furthermore, don't we usually want to extract the original type when programming? When switching between something, like async a -> a or maybe a -> a... Isn't that a common operation? I can definitely see the case where somebody wants to optimize a monad out if they see it as negligible (e.g. a logging monad).
Additionally, what about layered monads without flattening? I understand that lists can be seen as monads where restricting flattening is a clear and logical choice, but what about the hypothetical case of async (async a) monadic values where async has no flatten function? Does bind only imply one layer of "monadic reduction" where we can often assume that (M a -> (a -> M a) -> M a) can often be seen as (M a -> (M a -> a) -> (a -> M a) -> M a), and (M M a -> (a -> M a) -> M a or M M a) may not work? Is there a true difference between flattening and non-flattening monads?

Won't this usually cause a problem?
You might say that this is "by design". One of the possible uses is IO; once you have a value tainted with IO, you have to "bubble up"; you can't hide the fact that a function is doing IO under a pure value.
wouldn't that mean I either have to manually convert each (a -> b) -> (a -> M b) by applying a monadic constructor somewhere?
This is easier than you think because every Monad is also a Functor and an Applicative Functor:
randomDice :: IO Int
randomDice = randomRIO (1,6)
cheat :: Int -> Int
cheat = (+1)
main = do
dice <- randomDice
dice' <- cheat <$> randomDice
Having all of the fmap, <$>, liftA/liftM and pure/return machinery at our disposal, it makes it very simple to easily use pure functions in the monadic contexts.
(M (M a) -> M a) is not implicitly required
That one is false. You only need bind to implement it.
join :: (Monad m) => m (m a) -> m a
join x = x >>= id

Related

haskell: calling a function with different types of lists

I have a function:
sum f l1 l2 = (f l1) + (f l2)
How to correct this function to be working when called with different types of lists? eg:
sum length [1,2] ['a','b']
May as well flesh out my comment in an answer. The usual signature one may be tempted to give is
sum :: Num b => ([a] -> b) -> [a] -> [a] -> b
sum f l1 l2 = f l1 + f l2
The problem here is that the two lists must have the same type, which must be the input type of the function. The solution is to tell GHC that the function actually has the more general type forall a. [a] -> b, which means that we can pick multiple possibly different a instantiations and they all produce the same b.
{-# LANGUAGE RankNTypes #-}
sum' :: Num b => (forall a. [a] -> b) -> [c] -> [d] -> b
sum' f l1 l2 = f l1 + f l2
main = print $ sum' length [1,2] ['a','b']
There's no general way to do this at the moment unfortunately. You could try like this previous answer suggested as follows:
sum' :: Num b => (forall a. [a] -> b) -> [c] -> [d] -> b
sum' f l1 l2 = f l1 + f l2
And whilst this works with length, it doesn't really work with much else.
The issue is that the type signature in this answer Num b => forall a. [a] -> b. That means your function must work for all types of lists, and the only sensible function from Num b => forall a. [a] -> b is length. If you think there's another feel free to give me an example, but I suspect all the other examples are either variations of length or silly ones that return a constant.
And if length is the only sensible argument for sum', then it's silly to define sum', you might as well define sumLength like follows
sumLength :: Num b => [c] -> [d] -> b
sumLength l1 l2 = genericLength l1 + genericLength l2
Indeed, lets define the following:
g :: Enum a => [a] -> Int
g = (foldl' 0 (+)) . (map fromEnum)
This is a weird probably useless function, but it does something non-trivial. It converts all the values to their Enum int representation and sums them and spits out an Integer.
So sum' g l1 l2 should work, but it doesn't. To get this to work, you'd have to define a new function:
sum'' :: Enum c, Enum d => (Enum a => forall a. [a]) -> [c] -> [d] -> Int
sum'' f l1 l2 = f l1 + f l2
And indeed, too use any function with different constraints, you'll have to define a new version of sum.
So really, no, there's no way to answer your question similarly.
I recognised this problem and created the package polydata, which you can check out on hackage (needs some clearer documentation I admit).
It does allow you to make functions which accept polymorphic functions that you can apply to different types, like so:
g :: (c (a -> a'), c (b -> b')) => Poly c -> (a, b) -> (a' -> b')
g f (x,y) = (getPoly f x, getPoly f y)
Which is very similar to your example.
c in the above is a constraint, and looking at the type of g should help you understand what's happening.
Unfortunately, you can't just pass an ordinary function to g, you have to pass one wrapped in a Poly, which is non trivial as you don't get type inference for the Poly constraint (any ideas on how to make this nicer appreciated).
But if you've just got one or a few functions that need this polymorphic behaviour, I wouldn't bother with Poly. But for example, you're finding this issue coming up a lot (I found it came up a lot in unit testing, which is what inspired the creation of my package), then you might find polydata useful.
There's also heterolist, which I created as an extension to polydata allows you to create lists of mixed types and say, map over them in a type safe way. You might find that useful.

Modeling recursive fmap (sort of) over a list

I was wondering what the best way is to implement the following problem in a functional programming language (in this example Haskell):
You have a function (or a 'way') that turns 2 inputs, with the type a and b, in 2 ouputs of the same type (ex: Half adder). Lets call it f
in Haskell it would have this sort of type signature
a -> b -> (a, b)
And you have a list with elements of type a. (or another type of data structure).
Now if supplied with an initial b I want the following thing to happen (concept explained with recursive implementation):
Execute f with the initial b and the first element, modify the b and the element with the output of the function and repeat for the next element.
In Haskell:
exec _ [] _ = []
exec f (x:xs) b = let (x',b') = f x b in x':(exec f xs b')
What would be the best/most efficient way to model this sort of behavior.
It's mapM for the State monad.
OK, expanding a little.
Let's first enter this into ghci and see the type of the exec function:
Prelude> let {exec _ [] _ = []; exec f (x:xs) b = let (x',b') = f x b in x':(exec f xs b')}
Prelude> :t exec
exec :: (t2 -> t1 -> (t, t1)) -> [t2] -> t1 -> [t]
It's almost as you described, except that t and t2 don't have to be of the same type. That's good.
Now, another observation: we actually lose information, when we do what you describe. Specifically, we throw away the last value of b (or t, as ghci calls it). Let us preserve it for a moment; we can always throw it away later:
exec' _ [] b = ([], b)
exec' f (x:xs) b =
let (x',b') = f x b
(xs', b'') = exec' f xs b'
in (x':xs', b'')
And ghci says
Prelude> :t exec'
exec' :: (t2 -> t1 -> (t, t1)) -> [t2] -> t1 -> ([t], t1)
Than we can define
exec f xs b = fst $ exec' f xs b
But now the type of exec' contains a clear pattern. We can make it more explicit:
type S b c = b -> (c, b)
exec' :: (a -> S b c) -> [a] -> S b [c]
And now it's clear that S is almost exactly the State monad (well, it's actual definition in a modern setting is a bit more complicated, but not much: https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-State-Lazy.html#t:StateT); really, it's just a newtype:
newtype State b c = State {runState :: b -> (c, b)}
And if we generalize the type of exec' to use an arbitrary monad instead of State, we get
Monad m => (a -> m c) -> [a] -> m [c]
Of course, we can't know for sure that such a thing actually exists, since we only have an implementation for the State monad, but... it does. It's called mapM (again, it's actual definition in the modern setting is more complicated: https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:mapM) — which makes sense, since without a monad it would be just
(a -> c) -> [a] -> [c]
and that's exactly the type of map.
Of course, you can't be sure that exec' IS mapM without examining the latter's implementation. But in Haskell it just often happens that things that have the same type, if it's reasonably generic, are one and the same.
It also makes sense that State monad would be involved somehow — after all, you DO use b as a state, changing it as you go through the list.
So, if exec' is mapM, how do we get back to exec? Well, we need to go from the monadic value State b [c] to just [c], feeding it some b. We can — again — generalize; let's say, we go from State b d to d, without mentioning the list. And again — there is a function like that, it's called evalState: https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-State-Lazy.html#v:evalState.
So, finally, we are able to produce the final result:
eval f xs b = evalState (mapM (\x -> state (\b -> f x b)) xs) b
which we can shorten to
eval f xs b = evalState (mapM (\x -> state (f x)) xs) b
or just
eval f xs = evalState (mapM (state . f) xs)
or even
eval f = evalState . mapM (state . f)
We can make it completely point-free, but that would be pointless (and contain too many points):
eval = (evalState .) . mapM . (state .)

How to convert CPS-style gcd computation to use the Continuation Monad

Let us consider the following implementation of the Continuation monad, for CPS-style computations yielding and integer:
module Cont : sig
type 'a t = ('a -> int) -> int
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val callCC: (('a -> 'b t) -> 'a t) -> 'a t
end = struct
type 'a t = ('a -> int) -> int
let return x =
fun cont -> cont x
let bind m f =
fun cont -> m (fun x -> (f x) cont)
let callCC k =
fun cont -> k (fun x -> (fun _ -> cont x)) cont
end
How can we rewrite the CPS-style implementation of gcd computation (see How to memoize recursive functions?) and especially the memoization to take advantage of the Cont monad?
After defining
let gcd_cont k (a,b) =
let (q, r) = (a / b, a mod b) in
if r = 0 then Cont.return b else k (b,r)
I tried to use the type solver to give me cue about the type that the memoization function should have:
# let gcd memo ((a,b):int * int) =
Cont.callCC (memo gcd_cont (a,b)) (fun x -> x)
;;
val gcd :
(((int * int -> int Cont.t) -> int * int -> int Cont.t) ->
int * int -> (int -> 'a Cont.t) -> int Cont.t) ->
int * int -> int = <fun>
However I could not turn this hint into an actual implementation. Is someone able to do this? The logic behind using “callCC” in the memoization function is that if a value is found in the cache, then this is is an early exit condition.
I feel like the issue is that in his answer to How to memoize recursive functions?, Michael called CPS style what is not CPS style. In CPS style, the extra continuation argument k is used whenever one wants to return a value - the value is then applied to k instead.
This is not really what we want here, and not what implements:
let gcd_cont k (a,b) =
let (q, r) = (a / b, a mod b) in
if r = 0 then b else k (b,r)
Here, k is not used for returning (b is returned directly), it is used instead of performing a recursive call. This unwinds the recursion: within gcd_cont, one can think of k as gcd_cont itself, just like if let rec was used. Later on, gcd_cont can be turned into a truly recursive function using a fixpoint combinator, that basically "feeds it to itself":
let rec fix f x = f (fix f) x
let gcd = fix gcd_cont
(this is equivalent to the call function that Michael defines)
The difference with defining gcd directly using a let rec is that the version with unwinded recursion allows one to "instrument" the recursive calls, as the recursion itself is performed by the fixpoint combinator. This is what we want for memoization: we only want to perform recursion if the result is not in the cache. Thus the definition of a memo combinator.
If the function is defined with a let rec, the recursion is closed at the same time as defining the function, so one cannot instrument the recursive call-sites to insert memoization.
As a side note, the two answers basically implement the same thing: the only difference is the way they implement recursion in the fixpoint combinator: Michael's fixpoint combinator uses let rec, Jackson's one uses a reference, i.e. "Landin's knot" — an alternative way of implementing recursion, if you have references in your language.
Sooo, to conclude, I'd say implementing that in the continuation monad is not really possible / does not really make sense, as the thing was not CPS in the first place.

Is a state monad with two state variable types (in and out) still a monad?

Haskell's state monad State s a forces me to keep the same type of s during the whole do block. But since the state monad is really just a function, what if I define it as State i o a = State (i -> (o, a))?. The return and bind functions would look exactly the same as in the standard state monad, but with the types changed:
return :: a -> State st st a
bind :: (State i o a) -> (a -> (State o o' b)) -> (State i o' b)
I don't think is possible to implement Monad in Haskell using this definition because it expects a single State i o type in bind (only a can change). But this question is not about Haskell but about whether this would technically be a monad or not. Or if not, would it be some kind of superset of a monad (such that all the monad laws still apply but has some extra features)?
This is something I found would be useful in another language I'm working on, which is based on lambda calculus, so I'm using Haskell as a reference. I just don't want this to break other stuff later on where I'd expect the monad laws to apply.
What you are looking for is an indexed Monad. See e.g. the definition in category-extras:
The definition of an indexed Monad:
class IxApplicative m => IxMonad m where
ibind :: (a -> m j k b) -> m i j a -> m i k b
The State indexed Monad:
class IxMonad m => IxMonadState m where
iget :: m i i i
iput :: j -> m i j ()

Unsequence Monad function within Haskell

I'm having some real trouble designing the counterfunction of Haskell's sequence function, which Hoogle tells me doesn't yet exist. This is how it behaves:
ghci> sequence [Just 7, Just 8, Just 9]
Just [7,8,9]
ghci> sequence [getLine, getLine, getLine]
hey
there
stack exchange
["hey","there","stack exchange"] :: IO [String]
My problem is making a function like this:
unsequence :: (Monad m) => m [a] -> [m a]
So that it behaves like this:
ghci> unsequence (Just [7, 8, 9])
[Just 7, Just 8, Just 9]
ghci> sequence getLine
hey
['h','e','y'] :: [IO Char] --(This would actually cause an error, but hey-ho.)
I don't actually know if that's possible, because I'd be escaping the monad at some point, but I've made a start, though I don't know how to set a breakpoint for this recursive function:
unsequence m = (m >>= return . head) : unsequence (m >>= return . tail)
I realise that I need a breakpoint when the m here is equal to return [], but not all monads have Eq instances, so how can I do this? Is this even possible? If so, why and why not? Please tell me that.
You can't have an unsequence :: (Monad m) => m [a] -> [m a]. The problem lies with lists: you can't be sure how may elements you are going to get with a list, and that complicates any reasonable definition of unsequence.
Interestingly, if you were absolutely, 100% sure that the list inside the monad is infinite, you could write something like:
unsequenceInfinite :: (Monad m) => m [a] -> [m a]
unsequenceInfinite x = fmap head x : unsequenceInfinite (fmap tail x)
And it would work!
Also imagine that we have a Pair functor lying around. We can write unsequencePair as
unsequencePair :: (Monad m) => m (Pair a) -> Pair (m a)
unsequencePair x = Pair (fmap firstPairElement x) (fmap secondPairElement x)
In general, it turns out you can only define unsequence for functors with the property that you can always "zip" together two values without losing information. Infinite lists (in Haskell, one possible type for them is Cofree Identity) are an example. The Pair functor is another. But not conventional lists, or functors like Maybe or Either.
In the distributive package, there is a typeclass called Distributive that encapsulates this property. Your unsequence is called distribute there.
It is indeed not possible to create an unsequence function using monads alone. The reason is:
You can safely and easily create a monadic structure from a value using return.
However, it is not safe to remove a value from a monadic structure. For example you can't remove an element from an empty list (i.e. a function of the type [a] -> a is not safe).
Hence we have a special function (i.e. >>=) which safely removes a value from a monadic structure (if one exists), processes it and returns another safe monadic structure.
Hence it is safe to create a monadic structure from a value. However it is not safe to remove a value from a monadic structure.
Suppose we had a function extract :: Monad m => m a -> a which could “safely” remove a value from a monadic structure. We could then implement unsequence as follows:
unsequence :: Monad m => m [a] -> [m a]
unsequence = map return . extract
However, there's no safe way to extract a value from a monadic structure. Hence unsequence [] and unsequence Nothing will return undefined.
You can however create an unsequence function for structures that are both monadic and comonadic. A Comonad is defined as follows:
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
extend :: (w a -> b) -> w a -> w b
duplicate = extend id
extend f = fmap f . duplicate
A comonadic structure is the opposite of a monadic structure. In particular:
You can safely extract a value from a comonadic structure.
However you can't safely create a new comonadic structure from a value, which is why the duplicate function safely creates a new comonadic structure from a value.
Remember that the definition of unsequence required both return and extract? You can't safely create a new comonadic structure from a value (i.e. comonadic structures don't have return). Hence the unsequence function is defined as follows:
unsequence :: (Comonad m, Monad m) => m [a] -> [m a]
unsequence = map return . extract
Interestingly sequence works on simply monadic structures. So via intuition you might assume that unsequence works on simply comonadic structures. However it not so because you need to first extract the list from the comonadic structure and then put each element of the list into a monadic structure.
The general version of the unsequence function converts a comonadic list structure to a list of monadic structures:
unsequence :: (Comonad w, Monad m) => w [a] -> [m a]
unsequence = map return . extract
On the other hand the sequence function works on simply monadic structures because you are just folding the list of monadic structures into a monadic list structure by chaining all the monads:
import Control.Monad (liftM2)
sequence :: Monad m => [m a] -> m [a]
sequence = foldr (liftM2 (:)) (return [])
Hope that helps.