Skip to main content

Home/ Haskell/ Group items tagged blog

Rss Feed Group items tagged

Javier Neira

Applicative-what? Functor-who? « wxfz :: Blog - 0 views

  • Monads Are  a kind of abstract data type used to represent computations (instead of data in the domain model).
Javier Neira

Understanding Monads Via Python List Comprehensions « All Unkept - 0 views

  • But here we have taken it to a higher level -- the Monad interface is like an abstraction of any kind of container.
  • This in turn leads to the concept that a monadic value represents a computation -- a method for computing a value, bound together with its input value.
  • Writing monads is hard, but it pays off as using them in Haskell is surprisingly easy, and allows you to do some very powerful things.
  • ...3 more annotations...
  • One of them you have seen explicitly -- it's the 'return' method, responsible for packing things up into the monad. The other is called 'bind' or '>>=', and it does the 'unpacking' involved with the <- arrow in the do notation.
  • the 'bind' method doesn't really unpack and return the data. Instead, it is defined in such a way that it handles all unpacking 'internally', and you have to provide functions that always have to return data inside the monad.
  • It looks very much like 'unpack this data from the monad so I can use it', so it helps conceptually. In fact, together with the rest of the body of the 'do' block it forms an anonymous lambda function,
Javier Neira

A Neighborhood of Infinity: Haskell Monoids and their Uses - 0 views

  • The Writer MonadYou can think of monoids as being accumulators. Given a running total, n, we can add in a new value a to get a new running total n' = n `mappend` a. Accumulating totals is a very common design pattern in real code so it's useful to abstract this idea. This is exactly what the Writer monad allows. We can write monadic code that accumulates values as a "side effect". The function to perform the accumulation is (somewhat confusingly) called tell. Here's an example where we're logging a trace of what we're doing.
  • This is an implementation of the factorial function that tells us what it did.
  • We use runWriter to extract the results back out. If we run> ex1 = runWriter (fact1 10)we get back both 10! and a list of what it took to compute this.
  • ...6 more annotations...
  • and the monoid for addition is Sum
  • but there is a big advantage to using the Writer version. It has type signature f :: Integer -> Writer (Sum Integer) Integer. We can immediately read from this that our function has a side effect that involves accumulating a number in a purely additive way.
  • This is the Bool type with the disjunction operator, better known as ||.
  • "tell my caller if any value of r is ever 120"
  • One last application to mention is the Data.Foldable library. This provides a generic approach to walking through a datastructure, accumulating values as we go. The foldMap function applies a function to each element of our structure and then accumulates the return values of each of these applications. An implementation of foldMap for a tree structure might be
  • Suppose we want to accumulate two side effects at the same time. For example, maybe we want to both count instructions and leave a readable trace of our computation. We could use monad transformers to combine two writer monads. But there is a slightly easier way - we can combine two monoids into one 'product' monoid. It's defined like this:instance (Monoid a,Monoid b) => Monoid (a,b) where mempty = (mempty,mempty) mappend (u,v) (w,x) = (u `mappend` w,v `mappend` x)
Javier Neira

A Neighborhood of Infinity: The IO Monad for People who Simply Don't Care - 0 views

  • Many programming languages make a distinction between expressions and commands.
  • Like other languages it makes the distinction, and like other languages it has its own slightly idiosyncratic notion of what the difference is. The IO monad is just a device to help make this distinction.
  • There is no room for anything like a print command here because a print command doesn't return a value, it produces output as a side-effect
  • ...18 more annotations...
  • It's easy to use: you just write do and then follow it by an indented list of commands. Here's a complete Haskell program:
  • Note also that commands take arguments that can be expressions. So print (2*x) is a command, but 2*x is an expression. Again, little different from a language like Python.
  • So here's an interesting feature of Haskell: commands can return values. But a command that returns a value is different from an expression with a value.
  • We have to use <- instead of let ... = ... to get a returned value out of a command. It's a pretty simple rule, the only hassle is you have to remember what's a command and what's a function.
  • get2Lines = do line1 <- getLine line2 <- getLine return (line1,line2)
  • To introduce a list of commands, use do.To return a value from a command, use return.To assign a name to an expression inside a do block use let.To assign a name to the result of a command, use <-.
  • what's a command and what's an expression? If it has any chance of doing I/O it must be a command, otherwise it's probably an expression.
  • Everything in Haskell has a type, even commands. In general, if a command returns a value of type a then the command itself is of type IO a.
  • eturn is simply a function of type a -> IO a that converts a value of type a to a command of type IO a.
  • 5. The type of a sequence of commands is the type of the last line.
  • The type of an if statement is the type of its branches. So if you want an if statement inside a do block, it needs to be a command, and so its branches need to be commands also. So it's
  • If something is of type IO a then it's a command returning an value of type a. Otherwise it's an expression. That's the rule.
  • following the rules above it's completely impossible to put an executed command inside an expression.
  • As the only way to do I/O is with commands, that means you have no way to find out what Haskell is doing inside expressions.
  • If the type isn't IO a, then you can sleep at night in the confidence that there are no side effects.
  • One last thing. Much of what I've said above is false. But what I hope I have done is describe a subset of Haskell in which you can start some I/O programming without having a clue what a monad is.
  • The idea of capturing imperative computations in a type of (immutable) values is lovely. And so is the general pattern we call "monad".
  • main = do return 1 print "Hello"
1 - 16 of 16
Showing 20 items per page