patternMinor
How is IO a monad?
Viewed 0 times
monadhowstackoverflow
Problem
I am learning the Haskell programming language. From what I am reading, Input/Ouput (IO) raises challenges for Haskell's purity, since by definition we are interacting with the outside world. From Wikipedia:
In a purely functional language, such as Haskell, functions cannot have any externally visible side effects as part of the function semantics. Although a function cannot directly cause a side effect, it can construct a value describing a desired side effect, that the caller should apply at a convenient time.
In the Haskell notation, a value of type IO a represents an action that, when performed, produces a value of type a.
Soon, I learned that IO is an example of a Haskell monad. Although we don't get a lot of explanation of what monads are. From Functors, Applicatives, And Monads In Pictures
How to learn about Monads:
By now, I have read various definitions of - that they add context or create smaller programming languages inside a big one around a specific concept. Still trying to get a sense of what monads and how those ideas apply.
In Haskell,
https://stackoverflow.com/questions/44965/what-is-a-monad
Is there something algebraic going on here? What is so algebraic about IO?
I apologize for being language specific. My hope is that most of this discussion applies to all functional programming languages. Any errors in my discussion represent my own limited understanding of this area.
There is another definition of monad I found in nLab that is not even specific to programming languages.
In a separate question, I would like to understand how the category theory notion of monad matches with the CS definition in the case of Haskell.
In a purely functional language, such as Haskell, functions cannot have any externally visible side effects as part of the function semantics. Although a function cannot directly cause a side effect, it can construct a value describing a desired side effect, that the caller should apply at a convenient time.
In the Haskell notation, a value of type IO a represents an action that, when performed, produces a value of type a.
Soon, I learned that IO is an example of a Haskell monad. Although we don't get a lot of explanation of what monads are. From Functors, Applicatives, And Monads In Pictures
How to learn about Monads:
- Get a PhD in computer science.
- Throw it away because you don’t need it for this section!
By now, I have read various definitions of - that they add context or create smaller programming languages inside a big one around a specific concept. Still trying to get a sense of what monads and how those ideas apply.
In Haskell,
monad is another typeclass, with basically only one rule defining it. And IO is an instance of that.class Monad m where
(>>=) :: m a -> (a -> m b) -> m bhttps://stackoverflow.com/questions/44965/what-is-a-monad
Is there something algebraic going on here? What is so algebraic about IO?
I apologize for being language specific. My hope is that most of this discussion applies to all functional programming languages. Any errors in my discussion represent my own limited understanding of this area.
There is another definition of monad I found in nLab that is not even specific to programming languages.
In a separate question, I would like to understand how the category theory notion of monad matches with the CS definition in the case of Haskell.
Solution
TLDR: Haskell types and functions form a category and from that we notice that things with
In order to consider what it means for some type to be part of a monad triplet we must first consider what a category means in the Haskell sense.
We let our category
We can now look at endofunctors in Hask. The contain two parts, a map from types to types, and a map from functions to functions so that
Functors are therefore type constructors (which map types to types) paired with a function
So we can conclude that a natural transformation is something with the type
Finally we take note that the identity type constructor
is a functor with its map given by identity.
We're now prepared to discuss monads! A monad is a triplet of 3 things,
With the coherence conditions that
where the
The
We can view
So in essence, we have this abstract notion of monads in category theory and since Haskell types can be viewed as a category, we can apply normal category theoretic notions like monads and get common patterns out of them. That's it. There's no secret category theory juice lending higher meaning to monads beyond those coherence conditions.
This is actually quite a common pattern. Whenever we view something with categories, be it logic, semantics, or type systems, we can blindly apply the last 100 years of research to our new category and discover "new" abstractions.
>>= and return satisfy the rules for monads.In order to consider what it means for some type to be part of a monad triplet we must first consider what a category means in the Haskell sense.
We let our category
Hask be defined with objects as Haskell types and arrows to be functions. Each identity arrow is an instance of id and composition is the normal .. It's trivial to see that these satisfy the normal coherence conditions.We can now look at endofunctors in Hask. The contain two parts, a map from types to types, and a map from functions to functions so that
map g . map f=map (g . f)
map id=id
Functors are therefore type constructors (which map types to types) paired with a function
map which lifts arrows a -> b to arrows F a -> F b. We can also define natural transformations between them as something which "slides" a member of F a to a member of G a satisfying the normal coherence conditionsnat . fmap f=fmap f . nat
So we can conclude that a natural transformation is something with the type
nat :: forall a. F a -> G aFinally we take note that the identity type constructor
type Id a = ais a functor with its map given by identity.
We're now prepared to discuss monads! A monad is a triplet of 3 things,
- A functor,
F
- A natural transformation
returnbetweenIdandF
- A natural transformation
joinbetweenF x FandF
With the coherence conditions that
join . fmap join = join . join and join . fmap return = join . return = id.where the
x means the product of two functors which is just defined by composition of type constructors.The
IO monad has a return :: a -> IO a $\equiv$ Id a -> IO a. That's our first natural transformation. Our second isn't quite as easy, but we can define join asjoin :: IO (IO a) -> IO a
join = (>>= id)We can view
join as a sequencing operation. It takes all the actions stored in the structure of the outer IO and sticks them in front of all the actions in the inner IO, returning a bigger but flat IO a.So in essence, we have this abstract notion of monads in category theory and since Haskell types can be viewed as a category, we can apply normal category theoretic notions like monads and get common patterns out of them. That's it. There's no secret category theory juice lending higher meaning to monads beyond those coherence conditions.
This is actually quite a common pattern. Whenever we view something with categories, be it logic, semantics, or type systems, we can blindly apply the last 100 years of research to our new category and discover "new" abstractions.
Code Snippets
nat :: forall a. F a -> G atype Id a = ajoin :: IO (IO a) -> IO a
join = (>>= id)Context
StackExchange Computer Science Q#30757, answer score: 9
Revisions (0)
No revisions yet.