Is do-notation specific to "base:GHC.Base.Monad"? - haskell

The idea that the standard Monad class is flawed and that it should actually extend Functor or Pointed is floating around.
I'm not necessarily claiming that it is the right thing to do, but suppose that one was trying to do it:
import Prelude hiding (Monad(..))
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
join = (>>= id)
(>>=) :: m a -> (a -> m b) -> m b
a >>= t = join (fmap t a)
(>>) :: m a -> m b -> m b
a >> b = a >>= const b
So far so good, but then when trying to use do-notation:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
The compiler complains:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Question:
Does do-notation work only for base:GHC.Base.Monad? Is there a way to make it work with an alternative Monad class?
Extra context:
What I really want to do is replace base:Control.Arrow.Arrow with a "generalized" Arrow class:
{-# LANGUAGE TypeFamilies #-}
class Category a => Arrow a where
type Pair a :: * -> * -> *
arr :: (b -> c) -> a b c
first :: a b c -> a (Pair a b d) (Pair a c d)
second :: a b c -> a (Pair a d b) (Pair a d c)
(***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
(&&&) :: a b c -> a b c' -> a b (Pair a c c')
And then use the Arrow's proc-notation with my Arrow class, but that fails like in the example above of do-notation and Monad.
I'll use mostly Either as my pair type constructor and not the (,) type constructor as with the current Arrow class. This might allow to make the code of my toy RTS game (cabal install DefendTheKind) much prettier.

You need to use the NoImplicitPrelude extension for full rebindable syntax, including do and proc. In that case, you get the following, among other stuff:
"Do" notation is translated using whatever functions (>>=), (>>), and fail, are in scope (not the Prelude versions). List comprehensions, mdo (Section 7.3.6, “The recursive do-notation ”), and parallel array comprehensions, are unaffected.
You can also tweak some handling of negation, equality, literal values, and whatnot. Great way to obfuscate code!
p.s. -- If you're going to rebind the do syntax, what sigfpe calls "parameterized monads" are great fun. The same idea is available in category-extras under Control.Monad.Indexed. And yes, they do work with rebindable syntax, despite the wildly different type signatures!

Related

Taking monadic functions out of a monad

Haskell has the function join, which "runs" a monadic action which is inside a monad:
join :: Monad m => m (m a) -> m a
join m = m >>= \f -> f
We can write a similar function for monadic functions with one argument:
join1 :: Monad m => m (a -> m b) -> (a -> m b)
join1 m arg1 = m >>= \f -> f arg1
And for two arguments:
join2 :: Monad m => m (a -> b -> m c) -> (a -> b -> m c)
join2 m arg1 arg2 = m >>= \f -> f arg1 arg2
Is it possible to write a general function joinN, that can handle monadic functions with N arguments?
You can do something like this with a fair amount of ugliness if you really desire.
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
import Control.Monad (join, liftM)
class Joinable m z | z -> m where
joins :: m z -> z
instance Monad m => Joinable m (m a) where
joins = join
instance (Monad m, Joinable m z) => Joinable m (r -> z) where
joins m r = joins (liftM ($ r) m)
But, as you can see this relies on some shaky typeclass magic (in particular, the unenviable UndecidableInstances). It is quite possibly better—if ugly looking—to write all of the instances join1...join10 and export them directly. This is the pattern established in the base library as well.
Notably, inference won't work too well under this regime. For instance
λ> joins (return (\a b -> return (a + b))) 1 2
Overlapping instances for Joinable ((->) t0) (t0 -> t0 -> IO t0)
arising from a use of ‘joins’
Matching instances:
instance Monad m => Joinable m (m a)
-- Defined at /Users/tel/tmp/ASD.hs:11:10
instance (Monad m, Joinable m z) => Joinable m (r -> z)
-- Defined at /Users/tel/tmp/ASD.hs:14:10
but if we give an explicit type to our argument
λ> let {q :: IO (Int -> Int -> IO Int); q = return (\a b -> return (a + b))}
then it can still work as we hope
λ> joins q 1 2
3
This arises because with typeclasses alone it becomes quite difficult to indicate whether you want to operate on the monad m in the final return type of the function chain or the monad (->) r that is the function chain itself.
The short answer is no. The slightly longer answer is you could probably define an infix operator.
Take a look at the implementation for liftM: http://hackage.haskell.org/package/base-4.7.0.2/docs/src/Control-Monad.html#liftM
It defines up to liftM5. This is because it's not possible to define liftMN, just like your joinN isn't possible.
But we can take a lesson from Appicative <$> and <*> and define our own infix operator:
> let infixr 1 <~> ; x <~> f = fmap ($ x) f
> :t (<~>)
(<~>) :: Functor f => a -> f (a -> b) -> f b
> let foo x y = Just (x + y)
> let foobar = Just foo
> join $ 1 <~> 2 <~> foobar
Just 3
This is quite reminiscent of a common applicative pattern:
f <$> a1 <*> a2 .. <*> an
join $ a1 <~> a2 .. <~> an <~> f
A single function for every possible N? Not really. Generalizing over functions with different numbers of arguments like this is difficult in Haskell, in part because "number of arguments" is not always well-defined. The following are all valid specializations of id's type:
id :: a -> a
id :: (a -> a) -> a -> a
id :: (a -> a -> a) -> a -> a -> a
...
We'd need some way to get N at the type level, and then do a different thing depending on what N is.
Existing "variadic" functions like printf do this with typeclasses. They establish what N is by induction on ->: they have a "base case" instance for a non-function type like String and a recursive instance for functions:
instance PrintfType String ...
instance (PrintfArg a, PrintfType r) => PrintfType (a -> r) ...
We can (after a lot of thinking :P) use the same approach here, with one caveat: our base case is a bit ugly. We want to start with the normal join, which produces a result of type m a; the problem is that to support any m a, we have to overlap with normal functions. This means that we need to enable a few scary extensions and that we might confuse the type inference system when we actually use our joinN. But, with the right type signatures in place, I believe it should work correctly.
First off, here's the helper class:
class Monad m => JoinN m ma where
joinN :: m ma -> ma
ma will take the relevant function type like a -> m b, a -> b -> m c and so on. I couldn't figure out how to leave m out of the class definition, so right off the bat we need to enable MultiParamTypeClasses.
Next, our base case, which is just normal join:
instance Monad m => JoinN m (m a) where
joinN = join
Finally, we have our recursive case. What we need to do is "peel off" an argument and then implement the function in terms of a smaller joinN. We do this with ap, which is <*> specialized to monads:
instance (Monad m, JoinN m ma) => JoinN m (b -> ma) where
joinN m arg = joinN (m `ap` return arg)
We can read the => in the instance as implication: if we know how to joinN an ma, we also know how to do a b -> ma.
This instance is slightly weird, so it requires FlexibleInstances to work. More troublingly, because our base case (m (m a)) is made up entirely of variables, it actually overlaps with a bunch of other reasonable types. To actually make this work we have to enable OverlappingInstances and IncoherentInstances, which are relatively tricky and bug-prone.
After a bit of cursory testing, it seems to work:
λ> let foo' = do getLine >>= \ x -> return $ \ a b c d -> putStrLn $ a ++ x ++ b ++ x ++ c ++ x ++ d
λ> let join4 m a b c d = m >>= \ f -> f a b c d
λ> join4 foo' "a" "b" "c" "d"
a b c d
λ> joinN foo' "a" "b" "c" "d"
a b c d

A -> IO B to IO (A -> B)

I want to convert a function A -> IO B to IO (A -> B), knowing that there is only a finite number of possible values of A. At the moment I just do
convert :: (A -> IO B) -> IO (A -> B)
convert f = do
b1 <- f a1
b2 <- f a2
...
let f' a1 = b1
f' a2 = b2
...
return f'
However I'm not satisfied with the amount of code this requires.
A slightly souped-up version of Joachim's answer, that uses Data.Map to perform the lookup faster. I'll be using the TupleSections pragma as well.
{-# LANGUAGE TupleSections #-}
import Data.Map
import Control.Monad
For added neatness, assume that your Piece type can be given Ord, Bounded and Enum instances.
data Piece = Knight | Bishop | Rook deriving (Ord,Bounded,Enum,Show)
and define the useful enumerate function
enumerate :: (Bounded a, Enum a) => [a]
enumerate = [minBound..maxBound]
Now you can do
convert :: (Monad m, Bounded a, Enum a, Ord a) => (a -> m b) -> m (a -> b)
convert f = do
memo <- sequence [liftM (a,) (f a) | a <- enumerate]
return (fromList memo!)
If you have a list values :: [A], and A has an Eq-Instance, this would work:
convert :: (A -> IO B) -> IO (A -> B)
convert f = do
lookupTable <- sequence [ (\b -> (a,b)) `fmap` f a | a <- values]
return $ (\a -> fromJust (lookup a lookupTable))
As other have noted, if you don’t mind the additional type class requirements for A, you can use maps or hashmaps to speed up the lookup.
Also, from your use-case description, it seems that you are loading static data from a file that comes with your program. Depending on the environment where your final program runs (e.g. guaranteed that the files exist and are not changing), this might be a valid use for unsafePerformIO to simply define A -> B as a top-level function. Alternatively there are ways to include binary blobs in the compile source.
For the sake of completeness, I'll mention that the countable package on Hackage makes this possible by providing the Finite type class. You define something like
instance Finite Piece where
allValues = [Pawn, Knight, Bishop, Rook, Queen, King]
then you have
assemble :: (Finite a, Applicative f) => (a -> f b) -> f (a -> b)
which will specialise to precisely what you need.
Looking at the source, it seems that it uses an association list, so it would be slow if your type was large. Plus, it defines some orphan instances of Foldable and Traversable and Eq (!) for functions, which some may regard as distasteful.
You have function f :: A -> IO B and you have g :: IO A,
you use your convert function with Applicative <*> :: f (a -> b) -> f a -> f b as
fg :: IO a -> (a ->IO B) -> IO B
fg g f = (convert f) <*> g
But you can just use monad (>>=) :: m a -> (a -> m b) -> m b,
fg :: IO a -> (a ->IO B) -> IO B
fg g f = g >>= f
Your function signature permits any function a->m b on input, yet inside you assume a specific range of values. convert is not as polymorphic as the signature seems to declare.
What you have done is created a Map from a to b, then made a pure function that looks up a pure value in that map. Here's why:
What you are asking for is similar to implementing tensorial strength strength :: (Monad m) => (a, m b) -> m (a, b) for a monoidal category (C, ⊗, I) - given a binary relation ⊗ in category C and a monad m, convert a ⊗ m b to m (a ⊗ b). When this is possible for a binary relationship that meets certain requirements, the monad is strong. In Haskell all monads are strong, if tensorial product a ⊗ b is chosen to be a pair (a, b): strength (a, mb) = mb >>= return . (a,). Yet, here you are attempting to do the same for a binary relationship ->. Unfortunately, a -> b cannot be chosen to be a tensor product, because it is not a bi-functor - it is contravariant in a. So what you want cannot be accomplished for arbitrary functions.
What is different in your case, is that essentially you built all pairs (a,b). The amount of code, therefore, can be reduced if you explicitly enumerate all possible pairs of a and b, for example by building a m (Map a b). The others here offered nice sugars exposing "function-like" interfaces, but they are merely lookups in the map.

A generic composition with ambiguity detection

I want to define a generic composition which works both for a -> b and for a -> Maybe b:
class Comp m where
(...) :: m a b -> m b c -> m a c
instance Comp (->) where
(...) = (>>>)
instance Comp (a -> Maybe b) where
(...) = (>=>)
Is it possible with all recent GHC extensions to define the second instance without a newtype wrapper similar to Control.Arrow.Kleisli?
Another problem is that the instances overlap, so for Just ... Just two equally sensible instances are possible. Is it possible to redesign ... so Just ... Just has polymorphic type so both a -> Maybe (Maybe a) and a -> Maybe a are valid typings for it?
If it's not possible maybe it's possible to defer implementation selection somehow. E.g.
data Comp a b = Comp a b
(...) = Comp
($$$) =
($$$) lifts generic compositions (which can be anything - not necessarily functions) to functions. Then Just ... Just $$$ (fromJust . fromJust)
This is probably not what you are looking for, but it will allow the instances to be defined. Explicit type annotations will often be required to select the appropriate instance. Using your example, Just ... Just is typed as Comp (->) a (Maybe a) b (Maybe b) => a -> Maybe b. FunctionalDependencies might help on cutting down when explicit type annotations are required, but would also restrict the possible instances to less than what you would like.
{-# LANGUAGE MultiParamTypeClasses #-}
import Control.Category
import Control.Monad
class Comp m a b b' c where
(...) :: m a b -> m b' c -> m a c
instance Comp (->) a b b c where
(...) = (>>>)
instance Monad m => Comp (->) a (m b) b (m c) where
(...) = (>=>)

Does a function like this already exist? (Or, what's a better name for this function?)

I've written code with the following pattern several times recently, and was wondering if there was a shorter way to write it.
foo :: IO String
foo = do
x <- getLine
putStrLn x >> return x
To make things a little cleaner, I wrote this function (though I'm not sure it's an appropriate name):
constM :: (Monad m) => (a -> m b) -> a -> m a
constM f a = f a >> return a
I can then make foo like this:
foo = getLine >>= constM putStrLn
Does a function/idiom like this already exist? And if not, what's a better name for my constM?
Well, let's consider the ways that something like this could be simplified. A non-monadic version would I guess look something like const' f a = const a (f a), which is clearly equivalent to flip const with a more specific type. With the monadic version, however, the result of f a can do arbitrary things to the non-parametric structure of the functor (i.e., what are often called "side effects"), including things that depend on the value of a. What this tells us is that, despite pretending like we're discarding the result of f a, we're actually doing nothing of the sort. Returning a unchanged as the parametric part of the functor is far less essential, and we could replace return with something else and still have a conceptually similar function.
So the first thing we can conclude is that it can be seen as a special case of a function like the following:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth f g a = f a >> g a
From here, there are two different ways to look for an underlying structure of some sort.
One perspective is to recognize the pattern of splitting a single argument among multiple functions, then recombining the results. This is the concept embodied by the Applicative/Monad instances for functions, like so:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth f g = (>>) <$> f <*> g
...or, if you prefer:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth = liftA2 (>>)
Of course, liftA2 is equivalent to liftM2 so you might wonder if lifting an operation on monads into another monad has something to do with monad transformers; in general the relationship there is awkward, but in this case it works easily, giving something like this:
doBoth :: (Monad m) => ReaderT a m b -> ReaderT a m c -> ReaderT a m c
doBoth = (>>)
...modulo appropriate wrapping and such, of course. To specialize back to your original version, the original use of return now needs to be something with type ReaderT a m a, which shouldn't be too hard to recognize as the ask function for reader monads.
The other perspective is to recognize that functions with types like (Monad m) => a -> m b can be composed directly, much like pure functions. The function (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c) gives a direct equivalent to function composition (.) :: (b -> c) -> (a -> b) -> (a -> c), or you can instead make use of Control.Category and the newtype wrapper Kleisli to work with the same thing in a generic way.
We still need to split the argument, however, so what we really need here is a "branching" composition, which Category alone doesn't have; by using Control.Arrow as well we get (&&&), letting us rewrite the function as follows:
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a (b, c)
doBoth f g = f &&& g
Since we don't care about the result of the first Kleisli arrow, only its side effects, we can discard that half of the tuple in the obvious way:
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a c
doBoth f g = f &&& g >>> arr snd
Which gets us back to the generic form. Specializing to your original, the return now becomes simply id:
constKleisli :: (Monad m) => Kleisli m a b -> Kleisli m a a
constKleisli f = f &&& id >>> arr snd
Since regular functions are also Arrows, the definition above works there as well if you generalize the type signature. However, it may be enlightening to expand the definition that results for pure functions and simplify as follows:
\f x -> (f &&& id >>> arr snd) x
\f x -> (snd . (\y -> (f y, id y))) x
\f x -> (\y -> snd (f y, y)) x
\f x -> (\y -> y) x
\f x -> x.
So we're back to flip const, as expected!
In short, your function is some variation on either (>>) or flip const, but in a way that relies on the differences--the former using both a ReaderT environment and the (>>) of the underlying monad, the latter using the implicit side-effects of the specific Arrow and the expectation that Arrow side effects happen in a particular order. Because of these details, there's not likely to be any generalization or simplification available. In some sense, the definition you're using is exactly as simple as it needs to be, which is why the alternate definitions I gave are longer and/or involve some amount of wrapping and unwrapping.
A function like this would be a natural addition to a "monad utility library" of some sort. While Control.Monad provides some combinators along those lines, it's far from exhaustive, and I could neither find nor recall any variation on this function in the standard libraries. I would not be at all surprised to find it in one or more utility libraries on hackage, however.
Having mostly dispensed with the question of existence, I can't really offer much guidance on naming beyond what you can take from the discussion above about related concepts.
As a final aside, note also that your function has no control flow choices based on the result of a monadic expression, since executing the expressions no matter what is the main goal. Having a computational structure independent of the parametric content (i.e., the stuff of type a in Monad m => m a) is usually a sign that you don't actually need a full Monad, and could get by with the more general notion of Applicative.
Hmm, I don't think constM is appropriate here.
map :: (a -> b) -> [a] -> [b]
mapM :: (Monad m) => (a -> m b) -> [a] -> m b
const :: b -> a -> b
So perhaps:
constM :: (Monad m) => b -> m a -> m b
constM b m = m >> return b
The function you are M-ing seems to be:
f :: (a -> b) -> a -> a
Which has no choice but to ignore its first argument. So this function does not have much to say purely.
I see it as a way to, hmm, observe a value with a side effect. observe, effect, sideEffect may be decent names. observe is my favorite, but maybe just because it is catchy, not because it is clear.
I don't really have a clue this exactly allready exists, but you see this a lot in parser-generators only with different names (for example to get the thing inside brackets) - there it's normaly some kind of operator (>>. and .>> in fparsec for example) for this. To really give a name I would maybe call it ignore?
There's interact:
http://hackage.haskell.org/packages/archive/haskell98/latest/doc/html/Prelude.html#v:interact
It's not quite what you're asking for, but it's similar.

Monad "bind" function question

If I define the "bind" function like this:
(>>=) :: M a -> (a -> M' b) -> M' b
Will this definition help me if I want the result to be of a new Monad type, or I should use same Monad but with b in the same Monad box as before?
As I've mentioned in the comment, I don't think such operation can be safely defined for general monads (e.g. M = IO, M' = Maybe).
However, if the M is safely convertible to M', then this bind can be defined as:
convert :: M1 a -> M2 a
...
(>>=*) :: M1 a -> (a -> M2 b) -> M2 b
x >>=* f = convert x >>= f
And conversely,
convert x = x >>=* return
Some of such safe conversion methods are maybeToList (Maybe → []), listToMaybe ([] → Maybe), stToIO (ST RealWorld → IO), ... note that there isn't a generic convert method for any monads.
Not only will that definition not help, but it will seriously confuse future readers of your code, since it will break all expectations of use for it.
For instance, are both M and M' supposed to be Monads? If so, then how are they defined? Remember: the definition of >>= is part of the definition of Monad, and is used everywhere to define other Monad-using functions - every function besides return and fail themselves.
Also, do you get to choose which M and M' you use, or does the computer? If so, then how do you choose? Does it work for any two Monad instances, or is there some subset of Monad that you want - or does the choice of M determine the choice of M'?
It's possible to make a function like what you've written, but it surely is a lot more complicated than >>=, and it would be misleading, cruel, and potentially disastrous to try to cram your function into >>='s clothes.
This can be a complicated thing to do, but it is doable in some contexts. Basically, if they are monads you can see inside (such as Maybe or a monad you've written) then you can define such an operation.
One thing which is sometimes quite handy (in GHC) is to replace the Monad class with one of your own. If you define return, >>=, fail you'll still be able to use do notation. Here's an example that may be like what you want:
class Compose s t where
type Comp s t
class Monad m where
return :: a -> m s a
fail :: String -> m a
(>>=) :: (Compose s t) => m s a -> (a -> m t b) -> m (Comp s t) b
(>>) :: (Compose s t) => m s a -> m t b -> m (Comp s t) b
m >> m' = m >>= \_ -> m'
You can then control which types can be sequenced using the bind operator based on which instances of Compose you define. Naturally you'll often want Comp s s = s, but you can also use this to define all sorts of crazy things.
For instance, perhaps you have some operations in your monad which absolutely cannot be followed by any other operations. Want to enforce that statically? Define an empty datatype data Terminal and provide no instances of Compose Terminal t.
This approach is not good for transposing from (say) Maybe to IO, but it can be used to carry along some type-level data about what you're doing.
If you really do want to change monads, you can modify the class definitions above into something like
class Compose m n where
type Comp m n
(>>=*) :: m a -> (a -> n b) -> (Compose m n) b
class Monad m where
return :: a -> m a
fail :: String -> m a
(>>=) :: Compose m n => m a -> (a -> n b) -> (Compose m n) b
m >>= f = m >>=* f
(>>) :: Compose m n => m a -> (n b) -> (Compose m n) b
m >> n = m >>=* \_ -> n
I've used the former style to useful ends, though I imagine that this latter idea may also be useful in certain contexts.
You may want to look at this sample from Oleg: http://okmij.org/ftp/Computation/monads.html#param-monad

Resources