I don't use Haskell a lot, but I understand the concept of Monads.
I had been confused by Kleisli triple, and the category, however,
Although Haskell defines monads in terms of the return and bind functions, it is also possible to define a monad in terms of
return
and two other operations,join
andfmap
. This formulation fits more closely with the original definition of monads in category theory. Thefmap
operation, with type(t → u) → M t → M u
, takes a function between two types and produces a function that does the "same thing" to values in the monad. Thejoin
operation, with typeM (M t) → M t
, "flattens" two layers of monadic information into one.
helps me to the background principle of Monads.
The two formulations are related as follows:
fmap f m = m >>= (return . f)
join n = n >>= id
fmap :: (a -> b) -> (m a -> m b)
unit :: a -> m a
join :: m (m a) -> m a
>>= :: m a -> (a -> m b) -> m b
m >>= f = join $ fmap f m
My question is:
I think that since >>=
can be composed of fmap
and join
, a monadic function
a -> m b
is not required and normal functions a -> b
will satisfy the operation, but so many tutorials around the web still insist to use a monadic functions since that is the Kleisli triple and the monad-laws.
Well, shouldn't we just use non-monadic functions, as long as they are endo-functions, for the simplicity? What do I miss?
Related topics are
>>=
andreturn
to usefmap
andjoin
instead. Is the result clearer? Does it use less "monadic functions"? If so, then include such a sample in your question, to make it clearer what you wish could happen; if not, then you have your answer as to why it is not often done. Also see stackoverflow.com/q/35387237/625403, – amalloya -> m a
is not required? With onlyfmap,join,>>=
you can not definereturn
. Indeed,return
is the only primitive that lets us create a monadic value from a non-monadic value. If you prefer, I think you could replacereturn :: a -> m a
withbase :: m ()
satisfying a bunch of laws, and then havereturn x = fmap (const x) base
. – chireturn :: a -> m a
(notunit
),fmap :: (a -> b) -> m a -> m b
, and(>>=) :: m a -> (a -> m b) -> m b
. (With the requirementMonad m
.) If you get the types wrong, none of it makes any sense. – molbdniloreadIORef
in your proposed alternate world? Is it ana -> m b
function or ana -> b
function? If ana -> m b
function, is this suitable motivation for havinga -> m b
functions (it certainly is for me)? If not, why not? – Daniel Wagnera -> m b
is not required and normal functionsa -> b
will satisfy the operation"? You also said that, "It is clear to me that to make the code work in monadic way without monadic functions, all we have to do is create the composed bind with fmap*joint. The reason I don't put sample is I don't want make this topic limited to JavaScript and some concrete example." Why don't you share the code example? It would be really helpful for us to understand what you're trying to convey. – Aadit M Shah