Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this questionIn a comment to one of my answers, SO user sdcwc essentially pointed out that the following code:
comb 0 = [[]]
comb n =
let rest = comb (n-1)
in map ('0':) rest
++ map ('1':) rest
could be replaced by:
comb n = replicateM n "01"
which had me completely stunned.
Now I am looki开发者_JAVA百科ng for a tutorial, book or PDF that teaches these advanced concepts. I am not looking for a "what's a monad" tutorial aimed at beginners or online references explaining the type of replicateM
. I want to learn how to think in monads and use them effectively, monadic "patterns" if you will.
Take functions like sequence
, filterM
, liftM2
, join
and think how they work for each monad IO
, []
, (->) a
, Writer
, State
. For example, sequence
for IO monad executes IO actions sequentially:
[IO a] -> IO [a]
Write the signature and try to use them. Some combinations are interesting, some less.
Example for filter:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Monad
import Control.Monad.State
import Control.Monad.Reader
a = filterM (\x -> do putStrLn $ "Put " ++ show x ++ "?"
fmap (=="Y") getLine)
b = filterM (const [False,True])
c m xs = runState (filterM k xs) 0
where k x = do a <- get
let p = a + x <= m
when p $ put (a+x)
return p
d = filterM (flip id)
a
filters the list using IO - it asks the user about each item.
b
filters the list nondeterministically - every item is nondeterministically included and not included. As a result, you get powerset. (Try it!)
c
filters the list, maintaining state. In this case this is greedy knapsack - you've got knapsack of capacity m
and want to insert as many items from xs
.
d
filters the list, maintaining a read-only state. This isn't interesting. I used the filtering function as the state, and this gives flip filter
.
A single function filterM
can do all those things.
If you'll write similar code for other functions, you'll get enough intuition to notice monadic functions in other places. For example, how to get the following function?
dup f x = f x x
and what about dup' f x = f x x x
?
From my perspective (which certainly isn't universal), I'm indifferent to the list monad - in your example I'd (weakly) argue that as there are lots of list functionals it was as good as a coincidence that the solution was a monadic functional rather than just a list functional (or a generalization of a list functional through Data.Traversable or Data.Foldable).
For monadic patterns I think more about the effect than particular combinators - State models read-write state, Reader models read-only "state", Writer models write only "state", Maybe models partiality (so it can model errors without error messages), Either/Error models errors with tangible error codes or messages. As you get a handle on effects - you quickly realize you need to combine them so monad transformers become important.
There aren't any books yet on advanced Haskell except "The Fun of Programming" - this is a multi-author book collecting some quite disparate work, so it is worth browsing a copy before deciding whether or not its a book you'd want. Richard Bird's new book has many examples of advanced coding but it does this with simple, elegant code. Its a very good book though it isn't a book about advanced language features.
In the absence of books, papers are the best place as they are more polished than blogs. Most relevant is the Haskell Symposium (which used to be called the Haskell Workshop), check the link below for the proceedings which will list the papers presented, then do a search for anything you find interesting - in most cases the authors make the paper publicly available.
http://haskell.org/haskell-symposium/
This piece of code actually combines two pretty implicit facts about Haskell:
- That strings are by default lists of characters
- That lists are an implementation of the indeterminism monad, which enumerates all possible paths when combined.
The following code pieces are equivalent:
replicateM n "12"
replicateM n ['1', '2']
replicateM n $ do c <- ['1', '2']
return c
I would argue that the last version actually shows most cleanly what happens in this case: That we have a choice between '1' and '2' and that n of these choices are chained together. Once you understand that, you are as advanced in your Haskell understanding as you need to be. The rest is just a nice bit of obfuscation.
The really wild/awesome stuff with monads is when you move beyond the state monad and its subsets -- writer and reader -- and start thinking about Cont and List, and what they mean in terms of backtracking, combination and serach. I'll give more references later, but Oleg and Chung-chieh Shan's LogicT paper is a good start: http://okmij.org/ftp/Computation/monads.html
EZ Yang's adventures in three monads from MR 15: http://themonadreader.files.wordpress.com/2010/01/issue15.pdf
The answers to this question may also be of interest: Creative uses of monads
Look into the Typeclassopedia in TMR13. No one else has suggested it, and it has helped me think about the various type classes that Haskell provides immensely.
Note: it is being updated to a second edition, but the first edition is still relevant and informative.
Two good sources for me to learn about nice concepts of the Haskell language have been http://learnyouahaskell.com/ and http://www.realworldhaskell.org/blog/ both of which you can use online and for free .) - I hope they can give you some nice steps further. Even when they don't teach the most advanced concepts, they may give you a pretty good insight into what is there and what it might be usefull for.
精彩评论