There is a asks function for reader monad, which defined exactly as reader function, why it exists as a separate function with a definition the same as a reader? why not always use reader?
class Monad m => MonadReader r m | m -> r where
-- | Retrieves the monad environment.
ask :: m r
ask = reader id
-- | Executes a computation in a modified environment.
local :: (r -> r) -- ^ The function to modify the environment.
-> m a -- ^ #Reader# to run in the modified environment.
-> m a
-- | Retrieves a function of the current environment.
reader :: (r -> a) -- ^ The selector function to apply to the environment.
-> m a
reader f = do
r <- ask
return (f r)
-- | Retrieves a function of the current environment.
asks :: MonadReader r m
=> (r -> a) -- ^ The selector function to apply to the environment.
-> m a
asks = reader
I found the patches that introduced this redundancy to the transformers package and the mtl package. The patch/commit descriptions are... not super enlightening. However, in both cases, asks predates reader, and in both cases, the same change introduced the state and writer primitives.
So, some speculation:
It was observed that it's handy to have the core semantic thing that the transformer/monad class does as a concept represented in the library.
For predictability, that new primitives were named after the transformer that supplied that primitive and nothing else (StateT -> state; WriterT -> writer; ReaderT -> reader). This parallelism makes it easier for users to remember what the thing they want is called.
Since asks already existed, it was kept around for a modicum of backwards-compatibility.
If we wanted a definitive answer, we might have to ask Ed Kmett or Twan van Laarhoven, the apparent originators of the changes.
Related
What's the difference between
view :: MonadReader s m => Getting a s a -> m a
and
use :: MonadState s m => Getting a s a -> m a
in Control.Lens.Getter?
Taking a look at the type signatures, view takes a MonadReader (such as ReaderT) and use takes a MonadState (such as StateT). Now, view and use both have the same objective: extract a reasonable value from the thing we're looking at.
MonadReader represents read-only state. We can access the value within using ask. MonadState represents read-write state, which can be retrieved with get. So both view and use query the internal state of the monad given, but view calls ask whereas use calls get. Generally speaking, only one will be applicable to your situation.
A look at the source code for the two functions is not particularly enlightening unless you already understand how lenses are implemented (and if you do, then you probably understand the difference between view and use), so this is a good example of a situation where the type signatures can be much more enlightening than the code itself.
A lens getter gives us a function from its source to its target:
(^.) :: s -> Getting a s a -> a
flip (^.) :: Getting a s a -> s -> a
Any function can be made into a MonadReader computation, with the argument type of the function as the environment type:
asks :: MonadReader s m => (s -> a) -> m a
That being so, (^.) can be generalised to any MonadReader through asks, giving rise to view:
view :: MonadReader s m => Getting a s a -> m a
view g = asks (\s -> s ^. g)
(The definitions I'm using here aren't literally the ones you will find in the Control.Lens.Getter source, but they are equivalent to them as far as results go.)
In a similar way, any function can be made into a MonadState computation that leaves the state unchanged, with the argument type of the function as the state type:
gets :: MonadState s m => (s -> a) -> m a
Accordingly, (^.) can also be generalised to any MonadState through gets, resulting in use:
use :: MonadReader s m => Getting a s a -> m a
use g = gets (\s -> s ^. g)
From another angle, view and use can be seen as variants of asks and gets, respectively, that take a getter as argument, rather than a function directly.
On a final note about view, functions themselves are instances of MonadReader. That being so, view can be used as a prefix/non-operator version of (^.).
I have a hard time to grasp the following type class constraint of a Monad Reader function, that receive multiple variables,
local :: MonadReader r m => (r -> r) -> m a -> m a
How to correctly understand the type class constraint? which one is the type constructor, r or m or both? (from the m a part it suggests the type constructor is m).
Compared with for example the bind function, where the type class constraint admitted only single parameter;
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Unlike the local function above, it's obvious and easy to comprehend that the type class constraint for the bind function demand type constructor m to be a Monad instance.
In those cases it's best to look at the class (MonadReader) here.
There you'll find this:
class Monad m => MonadReader r m | m -> r where
and quite a bit more.
So here m is some monad and r will be the thing you read from (MonadReader is a so called monad-transformer ... well ok not quite - it's the class that is common to all those transformers - ReaderT is the transformer ... but that's really horrible to explain ... sorry)
local is used to change the thing you read from (I like to think of it as the configuration or the environment) - the r->r part - giving you a computation in the monad m that will do this change.
And if you read on in the documentation there is even an example of how to use this:
calculateContentLen :: Reader String Int
calculateContentLen = do
content <- ask
return (length content);
-- Calls calculateContentLen after adding a prefix to the Reader content.
calculateModifiedContentLen :: Reader String Int
calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen
main = do
let s = "12345";
let modifiedLen = runReader calculateModifiedContentLen s
let len = runReader calculateContentLen s
putStrLn $ "Modified 's' length: " ++ (show modifiedLen)
putStrLn $ "Original 's' length: " ++ (show len)
as you can see local is used here to add "Prefix " in front of the string
please note that the monad m in this example is not IO - it's Identity (basically nothing - it has no effect)
(I hope it's ok to copy and paste it ... if not please let me know or remove it)
I learned that Monad.Reader is actually an encapsulation of a function, namely:
newtype Reader r a = Reader { runReader :: r -> a }
Which is made an instance of Monad,
instance Monad (Reader r) where
return a = Reader $ \_ -> a
m >>= k = Reader $ \r -> runReader (k (runReader m r)) r
In contrast, I knew that (->) is also a Monad,
instance Monad ((->) r) where
return = const
f >>= k = \ r -> k (f r) r
From the definitions it's able to see that they actually behave the same exactly.
So are they interchangeable in all usages? And what's the actual significance of differing these two Monads?
TL;DR
They are the same.
Some history lessons
State, Writer and Reader were inspired by Mark P. Jones' Functional Programming with Overloading and
Higher-Order Polymorphism, where he defined Reader as follows:
A Reader monad is used to allow a computation to access the values held
in some enclosing environment (represented by the type r in the following
definitions).
> instance Monad (r->) where
> result x = \r -> x
> x `bind` f = \r -> f (x r) r
As a passing comment, it is interesting to note that these two functions are
just the standard K and S combinators of combinatory logic.
Later, he defines (almost) today's MonadReader:
Reader monads : A class of monads for describing computations that consult some fixed environment:
> class Monad m => ReaderMonad m r where
> env :: r -> m a -> m a
> getenv :: m r
> instance ReaderMonad (r->) r where
> env e c = \_ -> c e
> getenv = id
getenv is simply ask, and env is local . const. Therefore, this definition already contained all significant parts of a Reader. Ultimately, Jones defines the monad transformer ReaderT (BComp is backward composition):
To begin with, it is useful to define two different forms of composition; forwards (FComp) and backwards (BComp):
> data FComp m n a = FC (n (m a))
> data BComp m n a = BC (m (n a))
[omitting Functor, Monad and OutOf instances]
> type ReaderT r = BComp (r ->)
Since StateT, WriterT, and others had their non-transformer variant, it was only logical to have a Reader r, which really is the same as (->) r.
Either way, nowadays Reader, Writer and State are defined in terms of their transformer variant, and you use their respective Monad* typeclass (MonadReader).
Conclusion
So are they interchangeable in all usages?
Yes.
And what's the actual significance of differing these two Monads?
None, except that ReaderT is actually a monad transformer, which makes things easier.
They are both instance of the MonadReader class. So yes, you can use one instead of the other.
They are in fact the exact same.
We can make this more formal by mapping between them:
toArrow :: Reader r a -> r -> a and toReader :: (r -> a) -> Reader r a
with implementations toReader = Reader and toArrow = runReader.
Edit: The semantic behind a Reader is that it holds some read-only configuration which you can thread through your chain of computations.
You should always prefer a Reader over using the plain arrow type when your want to thread some configuration information, because it is part of a very generic interface that provides useful helper functions, a MonadReader class for manipulating Reader like data types as well as a ReaderT for stacking Monads.
The MArray class provides generic functions for working with mutable arrays of various sorts in both ST and IO contexts. I haven't been able to find a similar class for working with both STRefs and IORefs. Does such a thing exist?
The ref-fd package provides it:
class Monad m => MonadRef r m | m -> r where
[...]
or with type families, ref-tf:
class Monad m => MonadRef m where
type Ref m :: * -> *
[...]
Another answer suggested the monad-statevar package which doesn't have the functional dependency. It also has separate HasGet and HasPut members and no abstraction over the newRef functionality.
Aside from the different methods in each, the functional dependency is a design trade-off. Consider the following two simplified classes:
class MRef1 r m where
newRef1 :: a -> m (r a)
readRef1 :: r a -> m a
class MRef2 r m | m -> r where
newRef2 :: a -> m (r a)
readRef2 :: r a -> m a
With MRef1, both the monad type and the reference type can vary freely, so the following code has a type error:
useMRef1 :: ST s Int
useMRef1 = do
r <- newRef1 5
readRef1 r
No instance for (MRef1 r0 (ST s)) arising from a use of `newRef1'
The type variable `r0' is ambiguous
We have to add an extra type signature somewhere to say that we want to use STRef.
In contrast, the same code works fine for MRef2 without any extra signature. The signature on the definition saying that the whole code has type ST s Int, combined with the functional dependency m -> r means that there is only one r type for a given m type and so the compiler knows that our existing instance is the only possible one and we must want to use STRef.
On the flip side, suppose we want to make a new kind of reference, e.g. STRefHistory that tracks all the values that have ever been stored in it:
newtype STRefHistory s a = STRefHistory (STRef s [a])
The MRef1 instance is fine because we are allowed multiple reference types for the same monad type:
instance MRef1 (STRefHistory s) (ST s) where
newRef1 a = STRefHistory <$> newSTRef [a]
readRef1 (STRefHistory r) = head <$> readSTRef r
but the equivalent MRef2 instance fails with:
Functional dependencies conflict between instance declarations:
instance MRef2 (STRef s) (ST s) -- Defined at mref.hs:28:10
instance MRef2 (STRefHistory s) (ST s) -- Defined at mref.hs:43:10
I also mentioned the type family version, which is quite similar in expressive power to the functional dependency; the reference type is a "type function" of the monad type so there can again only be one per monad. The syntax ends up being a bit different and in particular you can just say MonadRef m in constraints, without stating what the reference type is within the constraint.
It's also plausible to have the reversed functional dependency:
class MRef2 r m | r -> m where
so that each reference type can live in just one monad, but you can still have several reference types for a monad. Then you'd need type signatures on your references but not on your monadic computations as a whole.
Control.Monad.StateVar has a typeclass which lets you get and put IORefs and STRefs identically.
While hacking something up earlier, I created the following code:
newtype Callback a = Callback { unCallback :: a -> IO (Callback a) }
liftCallback :: (a -> IO ()) -> Callback a
liftCallback f = let cb = Callback $ \x -> (f x >> return cb) in cb
runCallback :: Callback a -> IO (a -> IO ())
runCallback cb =
do ref <- newIORef cb
return $ \x -> readIORef ref >>= ($ x) . unCallback >>= writeIORef ref
Callback a represents a function that handles some data and returns a new callback that should be used for the next notification. A callback which can basically replace itself, so to speak. liftCallback just lifts a normal function to my type, while runCallback uses an IORef to convert a Callback to a simple function.
The general structure of the type is:
data T m a = T (a -> m (T m a))
It looks much like this could be isomorphic to some well-known mathematical structure from category theory.
But what is it? Is it a monad or something? An applicative functor? A transformed monad? An arrow, even? Is there a search engine similar Hoogle that lets me search for general patterns like this?
The term you are looking for is free monad transformer. The best place to learn how these work is to read the "Coroutine Pipelines" article in issue 19 of The Monad Reader. Mario Blazevic gives a very lucid description of how this type works, except he calls it the "Coroutine" type.
I wrote up his type in the transformers-free package and then it got merged into the free package, which is its new official home.
Your Callback type is isomorphic to:
type Callback a = forall r . FreeT ((->) a) IO r
To understand free monad transformers, you need to first understand free monads, which are just abstract syntax trees. You give the free monad a functor which defines a single step in the syntax tree, and then it creates a Monad from that Functor that is basically a list of those types of steps. So if you had:
Free ((->) a) r
That would be a syntax tree that accepts zero or more as as input and then returns a value r.
However, usually we want to embed effects or make the next step of the syntax tree dependent on some effect. To do that, we simply promote our free monad to a free monad transformer, which interleaves the base monad between syntax tree steps. In the case of your Callback type, you are interleaving IO in between each input step, so your base monad is IO:
FreeT ((->) a) IO r
The nice thing about free monads is that they are automatically monads for any functor, so we can take advantage of this to use do notation to assemble our syntax tree. For example, I can define an await command that will bind the input within the monad:
import Control.Monad.Trans.Free
await :: (Monad m) => FreeT ((->) a) m a
await = liftF id
Now I have a DSL for writing Callbacks:
import Control.Monad
import Control.Monad.Trans.Free
printer :: (Show a) => FreeT ((->) a) IO r
printer = forever $ do
a <- await
lift $ print a
Notice that I never had to define the necessary Monad instance. Both FreeT f and Free f are automatically Monads for any functor f, and in this case ((->) a) is our functor, so it automatically does the right thing. That's the magic of category theory!
Also, we never had to define a MonadTrans instance in order to use lift. FreeT f is automatically a monad transformer, given any functor f, so it took care of that for us, too.
Our printer is a suitable Callback, so we can feed it values just by deconstructing the free monad transformer:
feed :: [a] -> FreeT ((->) a) IO r -> IO ()
feed as callback = do
x <- runFreeT callback
case x of
Pure _ -> return ()
Free k -> case as of
[] -> return ()
b:bs -> feed bs (k b)
The actual printing occurs when we bind runFreeT callback, which then gives us the next step in the syntax tree, which we feed the next element of the list.
Let's try it:
>>> feed [1..5] printer
1
2
3
4
5
However, you don't even need to write all this up yourself. As Petr pointed out, my pipes library abstracts common streaming patterns like this for you. Your callback is just:
forall r . Consumer a IO r
The way we'd define printer using pipes is:
printer = forever $ do
a <- await
lift $ print a
... and we can feed it a list of values like so:
>>> runEffect $ each [1..5] >-> printer
1
2
3
4
5
I designed pipes to encompass a very large range of streaming abstractions like these in such a way that you can always use do notation to build each streaming component. pipes also comes with a wide variety of elegant solutions for things like state and error handling, and bidirectional flow of information, so if you formulate your Callback abstraction in terms of pipes, you tap into a ton of useful machinery for free.
If you want to learn more about pipes, I recommend you read the tutorial.
The general structure of the type looks to me like
data T (~>) a = T (a ~> T (~>) a)
where (~>) = Kleisli m in your terms (an arrow).
Callback itself doesn't look like an instance of any standard Haskell typeclass I can think of, but it is a Contravariant Functor (also known as Cofunctor, misleadingly as it turns out). As it is not included in any of the libraries that come with GHC, there exist several definitions of it on Hackage (use this one), but they all look something like this:
class Contravariant f where
contramap :: (b -> a) -> f a -> f b
-- c.f. fmap :: (a -> b) -> f a -> f b
Then
instance Contravariant Callback where
contramap f (Callback k) = Callback ((fmap . liftM . contramap) f (f . k))
Is there some more exotic structure from category theory that Callback possesses? I don't know.
I think that this type is very close to what I have heard called a 'Circuit', which is a type of arrow. Ignoring for a moment the IO part (as we can have this just by transforming a Kliesli arrow) the circuit transformer is:
newtype CircuitT a b c = CircuitT { unCircuitT :: a b (c, CircuitT a b c) }
This is basicall an arrow that returns a new arrow to use for the next input each time. All of the common arrow classes (including loop) can be implemented for this arrow transformer as long as the base arrow supports them. Now, all we have to do to make it notionally the same as the type you mention is to get rid of that extra output. This is easily done, and so we find:
Callback a ~=~ CircuitT (Kleisli IO) a ()
As if we look at the right hand side:
CircuitT (Kleisli IO) a () ~=~
(Kliesli IO) a ((), CircuitT (Kleisli IO) a ()) ~=~
a -> IO ((), CircuitT (Kliesli IO) a ())
And from here, you can see how this is similar to Callback a, except we also output a unit value. As the unit value is in a tuple with something else anyway, this really doesn't tell us much, so I would say they're basically the same.
N.B. I used ~=~ for similar but not entirely equivalent to, for some reason. They are very closely similar though, in particular note that we could convert a Callback a into a CircuitT (Kleisli IO) a () and vice-versa.
EDIT: I would also fully agree with the ideas that this is A) a monadic costream (monadic operation expecitng an infinite number of values, I think this means) and B) a consume-only pipe (which is in many ways very similar to the circuit type with no output, or rather output set to (), as such a pipe could also have had output).
Just an observation, your type seems quite related to Consumer p a m appearing in the pipes library (and probably other similar librarties as well):
type Consumer p a = p () a () C
-- A Pipe that consumes values
-- Consumers never respond.
where C is an empty data type and p is an instance of Proxy type class. It consumes values of type a and never produces any (because its output type is empty).
For example, we could convert a Callback into a Consumer:
import Control.Proxy
import Control.Proxy.Synonym
newtype Callback m a = Callback { unCallback :: a -> m (Callback m a) }
-- No values produced, hence the polymorphic return type `r`.
-- We could replace `r` with `C` as well.
consumer :: (Proxy p, Monad m) => Callback m a -> () -> Consumer p a m r
consumer c () = runIdentityP (run c)
where
run (Callback c) = request () >>= lift . c >>= run
See the tutorial.
(This should have been rather a comment, but it's a bit too long.)