Listã¢ããã使ãã¨ãSICPã®ambè©ä¾¡å¨ãè¡ããããªé決å®æ§è¨ç®ãã§ããã
ãã¨ãã°ããã¿ã´ã©ã¹æ°ãåæããã³ã¼ãã¯æ¬¡ã®ããã«æ¸ããã
-- ptriples.hs import Control.Monad -- guardé¢æ°ã使ããã ptriples = do a <- [1..] b <- [1..a] -- b <= a c <- [a..a+b] -- c ãæ辺ã¨ããã° a <= c ãã¤ä¸è§ä¸çå¼ãã c <= a+b guard (a*a + b*b == c*c) return (b,a,c) -- å°ããæ°ãã並ã¹ã main = mapM_ print ptriples
$ runghc ptriples.hs (3,4,5) (6,8,10) (5,12,13) ...
ããã¯ã次ã®Pythonã³ã¼ãã¨ã»ã¼åãããã«åä½ããã
# -*- coding: utf-8 -*- # ptriples.py import itertools def ptriples(): for a in itertools.count(1): # ç¡éãªã¹ã [1..] ã«ç¸å½ for b in xrange(1,a): for c in xrange(a,a+b): if a*a + b*b == c*c: yield (b,a,c) if __name__ == '__main__': for x in ptriples(): print x
$ python ptriples.py (3, 4, 5) (6, 8, 10) (5, 12, 13) ...
Haskellã®ã³ã¼ãã¯a,b,cã®åãããå¤ãåè£ã¨ãã¦å¤æ°ã®ããã«æ¸ããã¨ãã§ãããã宣è¨çãªè¦ãç®ã¨ãªã£ã¦ããã
ä»çµã¿
ã¾ããæåã«ç¤ºããã³ã¼ãã®doè¨æ³ããæ¬æ¥ã®ã¢ããã®è¨æ³ã«ç½®ãæãã¦ã¿ãã
ptriples = [1..] >>= (\a -> [1..a] >>= (\b -> [a..a+b] >>= (\c -> guard (a*a + b*b == c*c) >>= (\x -> return (b,a,c) ))))
ããã§ãHaskell 2010ã«ãããListã¢ããã®å®ç¾©ãè¦ã¦ã¿ãã
instance Monad [] where m >>= k = concat (map k m) return x = [x] fail s = []
ããªãã¡ãreturn
ã¯è¦ç´ ããªã¹ãã«å
¥ããbind
ã¯ãªã¹ãm
ã®åè¦ç´ ã«å¯¾ãã¦ãé¢æ°k
ãé©ç¨ããçµæãçµåããã
è¤æ°åéããå ´åã¯ãä¸è¨ã®ããã«ããããã®çµã¿åããã«ã¤ãã¦è¨ç®ãé²ãã
do a <- [1,2,3]; b <- [4,5]; return (a,b) == [1,2,3] >>= (\a -> [4,5] >>= (\b -> return (a,b))) == concat (map (\a -> [4,5] >>= (\b -> return (a,b))) [1,2,3]) == concat [[4,5] >>= (\b -> return (1,b)), [4,5] >>= (\b -> return (2,b)), [4,5] >>= (\b -> return (3,b))] {- [4,5] >>= (\b -> return (1,b)) == concat (map (\b -> return (1,b)) [4,5]) == concat [return (1,4), return (1,5)] == concat [[(1,4)], [(1,5)]] == [(1,4), (1,5)] -} == concat [[(1,4), (1,5)], [(2,4), (2,5)], [(3,4), (3,5)]] == [(1,4), (1,5), (2,4), (2,5), (3,4), (3,5)]
次ã«ãguard
é¢æ°ã«ã¤ãã¦å®ç¾©ã調ã¹ãã
class Monad m => MonadPlus m where Monads that also support choice and failure. Methods mzero :: m a the identity of mplus. It should also satisfy the equations mzero >>= f = mzero v >> mzero = mzero mplus :: m a -> m a -> m a an associative operation instance MonadPlus [] guard :: MonadPlus m => Bool -> m () guard b is return () if b is True, and mzero if b is False.
guard
ã¯ä¸ã¤ã®å¼æ°ãåããTrueã§ããã°Unit (()
)ãå¤ã«æã¤ã¢ããããFalseãªãmzeroãè¿ãã
ããã«ãmzeroã«å¯¾ãã¦bindã§é¢æ°ãä¸ããçµæã¯ã常ã«mzeroã«ãªãã
ã¤ã¾ããä¸åº¦guard
ã«ä¸ããå¼ãFalseã¨ãªãã¨ããã®å¾ã®bindã§ç¹ããè¨ç®ã®çµæã¯mzeroã«ãªãã
Listã¢ããã«ãããmzeroã¯ä»æ§ã§ã¯æè¨ããã¦ããªãããGHCã®å®è£ ã§ã¯ç©ºãªã¹ãã¨ãªã£ã¦ããã
instance MonadPlus [] where mzero = [] mplus = (++)
ã¤ã¾ããä¸è¨ã®ããã«guard
ã®å¼æ°ãçã¨ãªããã®ã ããæ®ãã
do a <- [1,2,3]; guard (a <= 2); return a == [1,2,3] >>= (\a -> guard (a <= 2) >>= (\b return a)) == concat (map (\a -> guard (a <= 2) >>= (\b return a)) [1,2,3]) == concat [guard (1 <= 2) >>= (\b return 1), guard (2 <= 2) >>= (\b return 2), guard (3 <= 2) >>= (\b return 3)] == concat [[()] >>= (\b return 1), [()] >>= (\b return 2), [] >>= (\b return 3)] -- return () == [()] {- [()] >>= (\b return 1) == concat (map (\b return 1) [()]) == concat [return 1] == concat [[1]] == [1] [] >>= (\b return 3) == concat (map (\b return 3) []) == concat [] == [] -} == concat [[1], [2], []] == [1,2]
以ä¸ãããæåã«ç¤ºããã³ã¼ãã¯guard
ã§ç¤ºããæ¡ä»¶ãæºãããã®ã®ãªã¹ããè¿ããã®ã¨ãªãã
é©ç¨ä¾
åå§ãã¿ã´ã©ã¹æ°
æåã®ã³ã¼ãã«aã¨bãäºãã«ç´ ã§ããã¨ããæ¡ä»¶ãå ããã°ãåå§ãã¿ã´ã©ã¹æ°ã®åæã«ãªãã ãã£ã¨ããåå§ãã¿ã´ã©ã¹æ°ã¯å ¬å¼ãç¨ãã¦åæã§ããã®ã§ãå ¬å¼ããæ±ããã»ããè¨ç®ã¯éãã
-- ptriples2.hs import Control.Monad -- guardé¢æ°ã使ããã ptriples = do a <- [1..] b <- [1..a] -- b <= a c <- [a..a+b] -- c ãæ辺ã¨ããã° a <= c ãã¤ä¸è§ä¸çå¼ãã c <= a+b guard (a*a + b*b == c*c && gcd a b == 1) return (b,a,c) -- å°ããæ°ãã並ã¹ã main = mapM_ print ptriples
$ runghc ptriples2.hs (3,4,5) (5,12,13) (8,15,17) ...
SEND + MORE = MONEY
æ¥æ¬èªã§ã¯è¦é¢ç®ã¨ãããããã
-- money.hs import Control.Monad import Data.List money = do let digits = [0..9] s <- digits e <- digits \\ [s,0] n <- digits \\ [s,e] d <- digits \\ [s,e,n] m <- digits \\ [s,e,n,d,0] o <- digits \\ [s,e,n,d,m] r <- digits \\ [s,e,n,d,m,o] y <- digits \\ [s,e,n,d,m,o,r] let toint xs = foldl1 ((+) . (10 *)) xs let [send, more, money] = map toint [[s,e,n,d], [m,o,r,e], [m,o,n,e,y]] guard (send + more == money) return (send, more, money) main = mapM_ print money
$ time runghc money.hs (9567,1085,10652) real 0m41.404s user 0m35.934s sys 0m5.064s
multiple-dwelling
SICPã§é決å®æ§è¨ç®ã®ä¾ã¨ãã¦åãä¸ãããã¦ããè«çããºã«ã
- Baker, Cooper, Fletcher, Miller, Smithã®5人ã5é建ã¦ã®ã¢ãã¼ãã®åããã¢ã«ä½ãã§ããã
- Bakerã¯5éã§ã¯ãªãã
- Cooperã¯1éã§ã¯ãªãã
- Fletcherã¯1éã§ã5éã§ããªãã
- Millerã¯Cooperããä¸ã®éã§ããã
- Smithã¯Fletcherã®ä¸ä¸ã®éã§ã¯ãªãã
- Fletcherã¯Cooperã®ä¸ä¸ã®éã§ã¯ãªãã
- ããããä½éã«ä½ãã§ãããï¼
-- dwelling.hs import Control.Monad import Data.List dwelling = do [baker, cooper, fletcher, miller, smith] <- permutations [1..5] guard (baker /= 5 && cooper /= 1 && fletcher `notElem` [1,5]) guard (miller > cooper) guard (abs(smith - fletcher) /= 1 && abs(fletcher - cooper) /= 1) return [("baker", baker), ("cooper", cooper), ("fletcher", fletcher), ("miller", miller), ("smith", smith)] main = mapM_ print dwelling
$ runghc dwelling.hs [("baker",3),("cooper",2),("fletcher",4),("miller",5),("smith",1)]