16 ms·
Haskell, Monads and Purity
- MichaelDickens 12y agoI think there's an important difference between saying Haskell uses monads to do IO and we use rings to do arithmetic. In Haskell, understanding monads helps you do lots of tasks more effectively, since so many data types are monads: IO, Maybe, lists, ... In math, there are other uses for rings, but if you're using them, it helps to know a little ring theory. Similarly, if you want to use any of the other Haskell monads, it helps to know how monads work.
- deleted 12y ago[deleted]
- Chinjut 12y agoYou say "I think there's an important difference", but then, you end up saying precisely the same things about monads and rings. What was the difference?
- brandonbloom 12y agoI sighed at the title, but was glad that I read the first paragraph. Very well put! I guess that I've got to read the rest of the article now too...
- tikhonj 12y agoYeah, this was more of a draft than a finished article. I didn't realize anyone was following my blog :P. It's a working title at best—it doesn't really reflect what I wanted to talk about... but then, I'm not sure the second half or so does either.
- carterschonwald 12y agois all of the code meant to be invisible? :)
- tikhonj 12y agoOh, that's a weird bug with the fonts... which I thought I had fixed. Unfortunately, I can't reproduce it locally, so I'm not sure I can do much about it right now.
- carterschonwald 12y agolooks fine now
- throwaway283719 12y agoI think you might have a bug -- return :: a -> State a get :: State Int set :: Int -> State Int -- should be Int -> State () surely?
- dschiptsov 12y agowhy, it is just an ADT which could be implemented in almost any language. Something like tagging a value with a type-tag and then define whole bunch of constructors and selectors, and then procedures which removes the tag, applies a given procedure and sticks the the tag to the result. (cons 'safe x) OK, In Haskell this stuff could be type-checked, which means only that the arguments to functions and its return values are of correct type (tags are present). But calling this a "safety" is a silly meme.)
- wyager 12y ago>which could be implemented in almost any language. You need HKTs to have type-checked generic monads. Almost no languages have them.
- wycats 12y agoYes, if you want type-checked generic monads. Dynamic languages can implement generic, but not type-checked monads. Many static languages can implement type-checked but non-generic monads. Now you need to show how type-checked generic monads are critical. That's much harder than showing that the monadic pattern is useful.
- tel 12y agoBeing able to abstract over the monad leads to monad transformers of the `transformers`, `mtl`, and `extensible-effects` varieties. You can argue that those aren't valuable, but I don't think you can argue that type-checked generic monads are critical for achieving them. In practice, 75% of the time that I use monads I am using some kind of monad stack. I'm sure you can argue that this is unnecessary or that I only do so because Haskell affords it... but on the other hand, I believe that transformer stacks do a good job of elaborating the space of effect types with an efficient, expressive language. Without them you either elide side effect reification or build a lot of one-off monad stacks.
- iopq 12y agoExcept in dynamic languages most people reinvent the wheel and don't quite get to a monadic interface. Like Javascript promises. They could have had ONE interface that is consistent. But Promises are actually a special snowflake that solves the problem in a slightly different way with a slightly different interface. And that's because nobody can complain that their stuff doesn't compile due to it not satisfying some interface.
- teyfille 12y agoHaskell's rhetoric has always seemed a bit Pharisaical to me: "Though the runtime is impure, Our Code is uncontaminated by the taint of side effects".
- zoomerang 12y agoNot really. The point of Haskell is not to avoid having side effects. The point of Haskell is to allow code to be referentially transparent - this makes it both easier to reason about as a developer, and easier for the runtime to optimise.
- teyfille 12y agoYes, that is altar upon which you sacrifice the abilitity to write print statements to do debugging, and lose the ability to reason about order of execution. But does it really result in more performant code? Every benchmark I've ever seen, more practical languages like Ocaml have come out on top.
- fortknots 12y agoActually, Haskell does let you write print statements for debugging. If we have the following function: foo :: Int -> Int foo x = x `div` 0 and we want to add debugging, we can do: import Debug.Trace foo :: Int -> Int foo x | trace (show x) False = undefined | otherwise = x `div` 0 The above will print the value of x before throwing an error due to division by zero. You don't have to make foo return an IO Int or change any other aspect of your program.
- gamegoblin 12y agoSomething I like to do is: import Debug.Trace wtf v x = trace (show x) v someFunction x = anotherFunction x `wtf` x This allows me to tack `wtf` onto the end of otherwise unchanged expressions to do print debugging
- deleted 12y ago[deleted]
- spion 12y agoI think that the misconception the author talks about happens because a noun is used for the properties of an object. An adjective such as "monadic" can be used instead: "In Haskell, IO actions are monadic because the IO type has a flatMap (bind) operator and a unit (return) function which satisfy left identity, right identity and associativity". All of the above are the properties (traits?) of the IO datatype. Monads (in Haskell) don't "exist" by themselves, they're just a property.
- mattdw 12y agoIt took me so long to figure out that "where is the monad?" was the wrong question. It took me even longer to grok that "monad" is essentially an interface/trait rather than a "type". I think your suggestion of 'monadic' is a big improvement.
- tel 12y agoThis is pretty true and certainly important but "Monad" does exist for many reasons. It's essentialy standing for "a monadic type" used when you're given a value of some monadic type but no specific one. This happens (in various forms) a lot in Haskell and so the term has weight. But for learning purposes I agree wholeheartedly!
- dllthomas 12y agoI think a part of it is a slight weirdness of Haskell typeclasses. In math, the noun "monad" refers to is a triple containing a functor and two natural transformations. The equivalent noun in Haskell would be the typeclass instance for a particular type. However, because Haskell (basically) only allows one instance per type, you select different instances by choosing a different (possibly equivalent, as with newtype) type, and so there is some natural conflation that arises in the language people use to talk about these things. The dynamic may be slightly clearer for semigroups. In mathematics, a semigroup is a pair containing a set and an (associative) operation on that set. In Haskell we say things like "ByteString is a semigroup" but that's short for "there is a semigroup where the set is all possible ByteStrings" and you assume the people you're talking to understand what the operation is because there is only one instance of Semigroup commonly defined for ByteString.
- lpw25 12y ago> This is why unsafePerformIO is unsafe: it’s completely foreign to the programming model Maybe, although it is also not type safe because Haskell doesn't have a value restriction for polymorphism. (or looked at another way Haskell's value restriction assumes that function application is a value).
- tel 12y agoIt's not really trying to be type safe either. There are lots of ways to break types with unsafePerformIO
- tikhonj 12y agoAnd, by extension, we don't have a value restriction because unsafePerformIO is foreign to our programming model. If it was actually part of the abstraction, Haskell would be a lot more like ML!