Haskellã§æ¸ããããããããFizzBuzz â Haskellã§èªããªãã³ã¼ãã«ééããæã«è§£èªããæ¹æ³ãå¾¹åºè§£èª¬ï¼
Haskellã«ã¯æ½è±¡çãªé«é颿°ãæ¼ç®åãããã¤ãããããã¾ã«ããããå·§å¦ã«ç¨ããã³ã¼ããã§ã¦ãã¦æå¿ãããã¨ãããã¾ãã ä»ã®äººãæ¸ããHaskellã®ã³ã¼ããèªãã§ããã¨ããªããªãé¢ç½ããã®ã¨ééããããã¾ãã å·§å¦ã«æ¸ãããã³ã¼ããè§£èªãã¦ããã¨ãå®ã¯åã¯ã©ã¹ã®instanceããã¾ãçµã¿åããã¦ä½¿ã£ã¦ãã¦ãã¨ã¦ãããææã«ãªããã¨ãããã¾ãã
å®éã«ã¢ããªã±ã¼ã·ã§ã³ã³ã¼ããæ¸ãã¦ãã¦ããã¾ã§æå·§çãªã³ã¼ããæ¸ãããã§ã¯ããã¾ãããããããããããã³ã¼ããèªã¿è§£ãã®ã¯åã¯ã©ã¹ã®ããç·´ç¿ã«ãªãã¾ãããããã¾ã§ç¥ããªãã£ãinstanceã¨ééãããããã¨ãã¯ãã¨ã¦ãåå¼·ã«ãªãã®ã§ãã
ãã®ã¨ã³ããªã¼ã§ã¯ãã¨ã¦ãæå·§çãªFizzBuzzãç´¹ä»ãããããèªã¿è§£ãã¦ããæ¹æ³ãç´¹ä»ãã¾ãã Haskellã®åå¿è åãã«ãã©ããããµãã«é¢æ°ãåã調ã¹ã¦è¨ã£ããããããä¸å¯§ã«æ¸ãã¦ãã¾ãã Haskellã®é£ããã³ã¼ãè¦ã¦ãä½ããæãä»ãã¦ãããåãããªãã¨ããæ¹ããããããHaskellã®ã³ã¼ãèªãæã£ã¦ã©ããã£ã¦ãªãã¡ã¬ã³ã¹ãå¼ãã®ï¼ã¨ããæ¹ã«ã¯ããã²é¢æ°ãåã¯ã©ã¹ãªã©ã調ã¹ãæ¹æ³ã身ã«ã¤ãã¦æ¬²ããã¨æãã¾ãã
注æ: ãã®è¨äºã®å
容ã¯å¤ããªã£ã¦ãã¾ããã彿ã®ã¾ã¾ããã¦æ¸ãç´ãã¦ãã¾ããã®ã§ã注æãã ããã<> ã¯ç¾å¨ã¯ Data.Semigroup ã®æ¼ç®åã§ãã
ç®æ¬¡
- ç®æ¬¡
- å°å ¥ â ãããããFizzBuzz
- ã³ã¼ããçè§£ããã
- åãã³ã¼ããæ¸ãã¦ã¿ãã
- ã¾ã¨ã
å°å ¥ â ãããããFizzBuzz
Twitterãçºãã¦ãããCAMPHOR- Advent Calendarã®26æ¥ç®ã®è¨äºãæµãã¦ãã¦ãHaskellã«é¢ããå
容ã ã£ãã®ã§éãã¦èªãã§ãã¾ããã
ryota-ka.hatenablog.com
ãã®è¨äºã§ã¯Monad (Either a)ã®>>=æ¼ç®åã使ã£ã¦ãã¾ãçµæãéãã¦ãã¾ããã
èªåãEitherã¨ãMonadã¨ã使ã£ãããããFizzBuzzãæ¸ãã¦ã¿ããã¨ãã¾ããããçµå±ãã¾ãæ¸ãã¾ããã§ããã
import Data.Maybe (catMaybes, listToMaybe) main = mapM_ (print . fizzbuzz) [1..100] fizzbuzz n = concat $ catMaybes [ listToMaybe [ "Fizz" | n `mod` 3 == 0 ], listToMaybe [ "Buzz" | n `mod` 5 == 0 ] ]
catMaybes :: [Maybe a] -> [a] ã使ã£ã¦mod 3ã¨mod 5ã®çµæãéãã¦ã¿ã¾ãããããã®å¾ã©ãããã°ãããããåããã¾ããã§ããã
ããã§concatã使ããã«listToMaybeãç¨ããã¨ã15ã®åæ°ã®Buzzãè½ã¡ã¦ãã¾ãã¾ãã
ãã¨è¨ã£ã¦""ãã¾ãNothingã«ãããããString -> Maybe Stringãæ¸ãã®ãããªãã䏿¦Stringã«è½ã¨ãããã®ãã¾ãæã¡ä¸ãã¦ããæãããã¦å«ãªæ°åã§ãã
[] -> Nothing ã§ãã以å¤ã®æã¯é¢æ°ããã¾ããã¨ãã§ããã[a] -> ([a] -> b) -> Maybe bãæ¸ãããã¨æãã¾ããããã©ãããã¬ã¤ãããªãæ°ããã¾ãã
綺éºã«æ¸ããªãã¦å°ã£ãã®ã§ãBeautiful FizzBuzz in Haskellã¨ãã§é©å½ã«ã°ã°ã£ã¦ã«ãã³ã¤ã¤FizzBuzzãæ¢ãã¦ããã¨ãããã¨ã¦ãè峿·±ãFizzBuzzãè¦ã¤ãã¾ããã
I finally bothered to implement FizzBuzz. I would fail the interview anyway, though...
let (m ~> str) x = str <$ guard (x `mod` m == 0) in map (fromMaybe . show <*> 3 ~> "fizz" <> 5 ~> "buzz")reddit Haskell: I Did A Haskell: fizzbuzz
ãªãã»ã©ããããã
ä½ããã£ã¦ããããã£ã±ãåããã¾ãããã(<>) ã (<*>) ãªã©ãå¹³åçãªHaskellerãæ®æ®µãã使ã£ã¦ããæ¼ç®åã§ãããã®ã³ã¼ãã«ãªãã¨ãªãã§ããã«ä½¿ããã®ããåã¯ã©ããã£ã¦åè´ãã¦ããã®ããããã«ã¯çè§£ã§ããªãã¨æãã¾ãã
ä¸ä½ã©ããªä»çµã¿ã§ãã®ã³ã¼ããæãç«ã£ã¦ããã®ãããããæ¸ãã人ã¯ã©ããã£ã¦ãã®ã³ã¼ããçµã¿ç«ã¦ãã®ãã調ã¹ã¦ã¿ã¾ãããã
ã³ã¼ããçè§£ããã
ã¾ãã¯å¿
è¦ãªã¢ã¸ã¥ã¼ã«ãªã©ãå«ããå®è¡ã§ããå½¢ã«ã³ã¼ããæ´ãã¦ã¿ã¾ããã
(GHC 7.10.x以éãã使ãã®æ¹ã¯ãControl.Applicativeã¨Data.Functorã®importã¯ä¸è¦ã§ãã)
import Control.Applicative ((<*>)) import Control.Monad (guard) import Data.Functor ((<$)) import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) main :: IO () main = mapM_ (putStrLn . fizzbuzz) [1..100] fizzbuzz :: Integer -> String fizzbuzz = let (d ~> s) n = s <$ guard (n `mod` d == 0) in fromMaybe . show <*> 3 ~> "Fizz" <> 5 ~> "Buzz"
ãã®ã³ã¼ããå®è¡ããã¨ããã¡ãã¨FizzBuzzã表示ããã¾ãã
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz ...
ããããã§ããã ã¡ããã¨FizzBuzzã«ãªã£ã¦ãã¾ãã ããã§ã¯ããã®ã³ã¼ããã©ãããä»çµã¿ã§åãã¦ããã®ã調ã¹ã¦ã¿ã¾ãããã
å忦: æ¼ç®å (~>)ã»Alternative
ã¾ãã¯letã®ã¨ããããã§ãã
fizzbuzz = let (d ~> s) n = s <$ guard (n `mod` d == 0) in fromMaybe . show <*> 3 ~> "Fizz" <> 5 ~> "Buzz"
æ¼ç®å(~>)ãå®ç¾©ãã¦ãã¾ãã
ghciã§ä¸å¯§ã«ããã®æ¼ç®åã®åã¨åä½ãè¦ã¦ããã¾ãã
$ ghci GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help Prelude> let (d ~> s) n = s <$ guard (n `mod` d == 0) <interactive>:2:23: Not in scope: âguardâ Prelude> :!hoogle guard | head -n 1 Control.Monad guard :: MonadPlus m => Bool -> m () Prelude> import Control.Monad Prelude Control.Monad> let (d ~> s) n = s <$ guard (n `mod` d == 0)
å®ç¾©ã§ããã®ã§ä½¿ã£ã¦ã¿ã¾ãããã ((<$)ããªãã¨è¨ãããå ´åã¯ã:import Data.Functorãã¦ä¸ãã)
Prelude Control.Monad> (3 ~> "Fizz") 1 <interactive>:21:1: No instance for (Show (f0 [Char])) arising from a use of âprintâ The type variable âf0â is ambiguous Note: there are several potential instances: instance (Show a, Show b) => Show (Either a b) -- Defined in âData.Eitherâ instance Show a => Show (Maybe a) -- Defined in âGHC.Showâ instance (Integral a, Show a) => Show (GHC.Real.Ratio a) -- Defined in âGHC.Realâ ...plus 15 others In a stmt of an interactive GHCi command: print it
åãéå®ãã¦ãããªãã¨è¡¨ç¤ºã§ããªããâ¦
ãªã«ãªã«ãf0ãææ§ï¼ãã¼ããã¾ãå·¦ã®ã»ãã§fromMaybeã¨ããã£ã¦ããMaybeã§ããããã
Prelude Control.Monad> (3 ~> "Fizz") 1 :: Maybe String Nothing Prelude Control.Monad> (3 ~> "Fizz") 3 :: Maybe String Just "Fizz" Prelude Control.Monad> map (3 ~> "Fizz") [1..20] :: [Maybe String] [Nothing,Nothing,Just "Fizz",Nothing,Nothing,Just "Fizz",Nothing,Nothing,Just "Fizz",Nothing,Nothing,Just "Fizz",Nothing,Nothing,Just "Fizz",Nothing,Nothing,Just "Fizz",Nothing,Nothing]
ãªãã»ã©ã
ãã®æ¼ç®åããã£ã¦ãããã¨ã¯ããã«çè§£ã§ãã¾ããã3 ~> "Fizz"ã¯ãã3ã®æã ãJust "Fizz"ã«ãªãã颿°ã§ãã
åãè¦ã¦ã¿ã¾ãããã
Prelude Control.Monad> :t (3 ~> "Fizz") (3 ~> "Fizz") :: (Integral a1, GHC.Base.Alternative f) => a1 -> f [Char] Prelude Control.Monad> :t ((3 ~> "Fizz") :: Integer -> Maybe String) ((3 ~> "Fizz") :: Integer -> Maybe String) :: Integer -> Maybe String
(3 ~> "Fizz") :: Integer -> Maybe String ã§ããã
ã¤ã¾ãã(~>)ã®åã¯
Prelude Control.Monad> :t (~>) (~>) :: (Integral a1, GHC.Base.Alternative f) => a1 -> a -> a1 -> f a Prelude Control.Monad> :t (~>) :: Integer -> String -> Integer -> Maybe String (~>) :: Integer -> String -> Integer -> Maybe String :: Integer -> String -> Integer -> Maybe String
ã§ãã
åã«:t æ¼ç®åããã ãã§ã¯ãéåãããããåãããªãåã表示ããã¾ããã
æç¤ºçã« :: T ã¨ã¤ãã¦ããã°ãããã§åãã§ãã¯ãéããã©ãã確ããããã¨ãã§ãã¾ãã
ããã§ã¯ã(~>)ã®ä¸ã§åãåã£ã¦ãããã¨ã確ããã¾ãã
Prelude Control.Monad> :t guard guard :: GHC.Base.Alternative f => Bool -> f () Prelude Control.Monad> :t (<$) (<$) :: Functor f => a -> f b -> f a
guardã¯f ()ãè¿ãã¾ãããã®fã¯ãMaybeã«éãããã¾ãããã¨ãããã¨ã¯â¦
Prelude Control.Monad> :t (guard :: Bool -> Maybe ()) (guard :: Bool -> Maybe ()) :: Bool -> Maybe () Prelude Control.Monad> :t (<$) :: String -> Maybe () -> Maybe String (<$) :: String -> Maybe () -> Maybe String :: String -> Maybe () -> Maybe String
ãªãã»ã©ãããããç»å ´äººç©ãã¡ã®åãããã£ã¦ãã¾ããã
guard :: Bool -> Maybe () (<$) :: String -> Maybe () -> Maybe String (~>) :: Integer -> String -> Integer -> Maybe String
ã§ããã
ããä¸åº¦ã(~>)ã®å®ç¾©ãè¦ã¦ã¿ã¾ãããã
(~>) :: Integer -> String -> Integer -> Maybe String (~>) d s n = s <$ guard (n `mod` d == 0)
dã¨nã¯Integerãsã¯"Fizz"ã®ãããªStringã§ãã
ãã¡ãã¨åããã£ã¦ãããã¨ãç®ã§è¦ã¦åããã¾ããã
(åãããªãã£ããä¸å¯§ã«ç´ã¨éçã§ç¢ºèªãã¾ãããï¼ã³ã¼ãã®ä¸ã«ç·ã§ãå¼ãã¦ããããã©ãããåã ããã¡ããã¨é©ç¨ã§ãããªãã¨ãããµãã«ç¢ºèªãã¾ãã)
ãã¨ã¯(<$)ã¨guardã®åä½ã確èªããã ãã§ãã
ã¾ããguardãã調ã¹ã¾ãããã
Hoogleã§guardã調ã¹ã¦ãããã¥ã¡ã³ãã«é£ã³ã¾ãã
guard :: Alternative f => Bool -> f ()guard b is pure () if b is True, and empty if b is False.The base package: Control.Monad
Alternativeãæ
£ãã¦ããªãã¨é£ããã§ããã
ä»åã®å ´åã¯guard :: Bool -> Maybe ()ãããªãã¡f = Maybeãªã®ã§ãinstance Alternative Maybeãæ¢ãã¾ãã
ä¸ã®ããã¥ã¡ã³ããéãã¦ãã¾ããï¼
guardã®åå®ç¾©ã®Applicativeã®ã¨ããã®ãªã³ã¯ãè¸ãã§ãã¾ãã¯Alternativeãã©ãããåã¯ã©ã¹ã ã£ããã調ã¹ã¾ãã
class Applicative f => Alternative f whereA monoid on applicative functors.
Minimal complete definitionempty, (<|>)The base package: Control.Applicative
Monoidã§ãããemptyã¯ã ãããåä½å
(mempty) ã§(<|>)ã¯ã ãããOR (mappend) ã§ã (ããªããã£ããããã¤ã¡ã¼ã¸ã§ã)ã
å°ãä¸ã«ãAlternative Maybeã®ãªã³ã¯ãããã¾ãã
å·¦ã®+ãã¯ãªãã¯ããã¨ãMaybeãã©ããã風ã«Alternativeã®instanceãªã®ããåããã¾ãããããããªããããããããªãã§ããã
ããããæã¯ãSourceã¨ããã¨ãããã¯ãªãã¯ãã¦ã½ã¼ã¹ã³ã¼ããè¦ã¾ãã
instance Alternative Maybe where empty = Nothing Nothing <|> r = r l <|> _ = l
ãªãã»ã©ãã¨ã¦ãç°¡æ½ã§ããã
ã ããããNothingã¯Falseã§(<|>)ã¯OR (||)ã®ãããªãã®ã§ãã
(||) :: Bool -> Bool -> Bool False || r = r l || _ = l
åãã§ãã
ãã¦ãguardã®èª¬æã¯ãguard b is pure () if b is True, and empty if b is False.ã§ãããemptyã®æå³ã¯instance Alternative Maybeã®å®ç¾©ããNothingã ã¨åããã¾ããããã¾ã pureãä½è
ããããåãã£ã¦ãã¾ããã
ããã§ãguardã®èª¬ææã®pureã®ãªã³ã¯ãè¸ãã¨ãApplicativeã«é£ã³ã¾ãã
Applicativeãä½ãã¯ã¨ããããç½®ãã¦ããã¦ãinstance Applicative Maybeãæ¢ãã¦ã½ã¼ã¹ã³ã¼ãã確èªãã¾ãã
instance Applicative Maybe where pure = Just Just f <*> m = fmap f m Nothing <*> _m = Nothing Just _m1 *> m2 = m2 Nothing *> _m2 = Nothing
ã¤ã¾ããpureã¯Justã¨ãããã¨ãåããã¾ããã
ã¾ã¨ããã¨ãguardã®èª¬æãBool -> Maybe ()ã«éãã¨ã次ã®ããã«ãªãã¾ãã
guard b is Just () if b is True, and Nothing if b is False.
ãããæ¬å½ããghciã§ç¢ºèªãã¾ãããã
Prelude Control.Monad> guard True :: Maybe () Just () Prelude Control.Monad> guard False :: Maybe () Nothing
確ãã«ããããªã£ã¦ãã¾ããã
TrueãªãJust ()ãè¿ããFalseãªãNothingãè¿ã颿°ã§ãã
ãã®æèã«ããã¦ãguardã¯Bool -> Maybe ()ã®ååååã§ããã
ãã¦ã(~>)ã®ä¸ã§guardã®åããåããã¾ããã
(~>) :: Integer -> String -> Integer -> Maybe String (~>) d s n = s <$ guard (n `mod` d == 0)
nãdã®åæ°ãªã s <$ Just () ã¨ãªããåæ°ã§ãªããªã s <$ Nothing ã¨ãªãã¾ãã
(~>)ã®åä½ããããã¨ã(<$)ã¯ãå³è¾ºãJust ()ãªã Just sãå³è¾ºãNothingãªãNothingãè¿ãã¨æ¨å¯ããã¾ãã
ããã§ã¯ã(<$)ã®å®ç¾©ãè¦ã¦ã¿ã¾ãããã
Hoogleã§<$ãæ¤ç´¢ããFunctorã®ããã¥ã¡ã³ãã«é£ã³ã¾ãã
(<$) :: a -> f b -> f aReplace all locations in the input with the same value. The default definition is fmap . const, but this may be overridden with a more efficient version.The base package: Data.Functor
ãªãã»ã©ãæçã«è¨ãã¨fmap . constã ã¨ãããã¨ããããã¾ããã
(<$)ã®é¨åãæ¸ãæãã¦ã¿ã¾ãã
(~>) d s n = (fmap . const) s (guard (n `mod` d == 0))
ããã¡ããç°¡ç´ï¼
(~>) d s n = fmap (const s) (guard (n `mod` d == 0))
ããããããï¼ããããè¦æ
£ããæãã«ãªãã¾ããã
guardã®è¿ãå¤ã¯ãJust ()ãNothingãªã®ã§ã
fmap (const s) (Just ()) ==> Just s fmap (const s) Nothing ==> Nothing
ã¨ãªããã¨ãåããã¾ãã
ãã®åä½ãä¸å®ã¨ããæ¹ã¯ãinstance Functor Maybeã確èªãã¦ä¸ããã
instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
fmapã¯Nothingã«ã¯ä½ããããJustã§å
ã¾ããå¤ã«ã¯é¢æ°ãé©ç¨ãã¦Justã§å
ãã§è¿ãã¾ãã
ãã®Maybe Functorã¯ã¨ã¦ãéè¦ãªFunctorãªã®ã§ãè¦ãã¦ããã¾ãããã
以ä¸ã§ã(~>)æ¼ç®åã®åããå®å
¨ã«è¿½ããã¨ãã§ãã¾ããã
let (d ~> s) n = s <$ guard (n `mod` d == 0)
3 ~> "Fizz" ã¯ã3ã®åæ°ã«ã¯Nothingãè¿ã (ããã§guardã®å¦çã¨instance Applicative Maybeã(<$) = fmap . constã¨instance Functor Maybeã®å®ç¾©ãããããã¨æãåºããªããåä½ã確èªãã¾ã)ã弿°ã3ã®åæ°ã§ã¯ãªããªãJust "Fizz"ãè¿ããããªé¢æ°ã§ãã
ã ãã ãããºã«ã®ç´ãè§£ãã¦ãã¾ããã
instance Alternative Maybeã®guard :: Bool -> Maybe ()ã§åæ°ãã©ããã¨ããBoolå¤ããMaybe ()ã«åããData.Functorã®æ¼ç®å(<$) = fmap . constã使ããã¦ãããããã§ã®Functorã®instanceã¯Maybe
å¾åæ¦: 颿°Applicativeã»é¢æ°Monoid
ããã§ã¯ãå¾åã調ã¹ã¦ããã¾ãããã
fromMaybe . show <*> 3 ~> "Fizz" <> 5 ~> "Buzz"
æ¼ç®åã4ã¤ããã¾ããã
(.)ã¯é »ç¹ã«ä½¿ããã颿°ã®åææ¼ç®åã§ã(~>)ã¯å
ç¨åä½ã確èªããæ¼ç®åã§ãã
(<*>)ã¯Applicativeã®æ¼ç®åã§(<>)ã¯Monoidã®æ¼ç®åãã¨ããç¥èã¯ãæã¡ã®æ¹ã¯å¤ãã§ãããã
ããããæ®æ®µä½¿ãæ¼ç®åã«ãé¢ãããããã®ã³ã¼ãããªããã¾ãåãã®ããããã¨ã¤ã¡ã¼ã¸ããã®ã¯é£ããã®ã§ã¯ãªãã§ããããã
ãããããããã®ã³ã¼ãã¯æå·§ã«å¯ãã§ãããã¨ã¬ã¬ã³ãã§ãããããããªã«ãã¨ã³ããªã¼ãæ¸ãã¦ãã¾ãã»ã©è峿·±ãã³ã¼ããªã®ã§ãã
ã¨ãããããfizzbuzz颿°ãghciã§å®ç¾©ãã¾ãããã
Prelude Control.Monad> let fizzbuzz = let (d ~> s) n = s <$ guard (n `mod` d == 0) in fromMaybe . show <*> 3 ~> "Fizz" <> 5 ~> "Buzz" <interactive>:42:64: Not in scope: âfromMaybeâ <interactive>:42:97: Not in scope: â<>â Prelude Control.Monad> import Data.Monoid Prelude Control.Monad Data.Monoid> import Data.Maybe Prelude Control.Monad Data.Monoid Data.Maybe> let fizzbuzz = let (d ~> s) n = s <$ guard (n `mod` d == 0) in fromMaybe . show <*> 3 ~> "Fizz" <> 5 ~> "Buzz" Prelude Control.Monad Data.Monoid Data.Maybe> :t fizzbuzz fizzbuzz :: (Integral a, Show a) => a -> String Prelude Control.Monad Data.Monoid Data.Maybe> map fizzbuzz [1..20] ["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz","16","17","Fizz","19","Buzz"]
ã§ãã¾ããã ã¡ããã¨åãã¦ãã¾ããã
ã¾ããæ¼ç®åã4ã¤ããã£ã¦ãã©ããããµãã«çµåãã¦ããããå®ãã§ã¯ããã¾ããã äºæ³ãã¤ãããã¨ã¯ã§ãã¾ããããã¡ãã¨çµåã®å¼·ãã確èªãã¦ããã¾ãã
Prelude Control.Monad Data.Monoid Data.Maybe> :i . (.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in âGHC.Baseâ infixr 9 . Prelude Control.Monad Data.Monoid Data.Maybe> :i <*> class Functor f => Applicative (f :: * -> *) where ... (<*>) :: f (a -> b) -> f a -> f b ... -- Defined in âGHC.Baseâ infixl 4 <*> Prelude Control.Monad Data.Monoid Data.Maybe> :i ~> (~>) :: (Integral a1, GHC.Base.Alternative f) => a1 -> a -> a1 -> f a -- Defined at <interactive>:12:8 Prelude Control.Monad Data.Monoid Data.Maybe> :i <> (<>) :: Monoid m => m -> m -> m -- Defined in âData.Monoidâ infixr 6 <>
ãã®infixrã¨ãinfixlã®å¾ã®æ°åã«çç®ãã¾ãã
ãã®æ°åã大ããæ¹ããå¼·ãçµåãã¾ãã
å¼·ãçµåããã¨ã¯ãæ¬å¼§ãçç¥ããæã«å
ã«çµã³ã¤ãã¨ãããã¨ã§ãã
ä¾ãã°ã1 + 2 * 3ã¯1 + (2 * 3)ã¨ãªãã¾ãããããã¯
Prelude> :i + class Num a where (+) :: a -> a -> a ... -- Defined in âGHC.Numâ infixl 6 + Prelude> :i * class Num a where ... (*) :: a -> a -> a ... -- Defined in âGHC.Numâ infixl 7 *
ã®ããã«ã(*)æ¼ç®åã®ã»ãã(+)æ¼ç®åãããçµåã®å¼·ããè¡¨ãæ°åã大ããããã§ãã
ããã§ã¯ä»åºã¦ãã4ã¤ã®æ¼ç®åã®çµåã®å¼·ãã¯
infixr 9 . infixr 6 <> infixl 4 <*>
ããã(~>)ã®çµåã®å¼·ãã¯ããããªã®ã§ããããï¼
æ¼ç®åã®çµåã®å¼·ãã¯æã
ãæç¤ºçã«æå®ãããã¨ãã§ãã¾ãããä»åã®å ´åã¯ä½ãæ¸ãã¦ãã¾ããã
æ¸ãã¦ããªãæã¯ã©ããªããã ã£ãã£ãã¨æã£ã¦haskell operator precedence rulesã®ãããªé©å½ãªåèªã§ã°ã°ãã¾ãã
ããããã¨ãThe Haskell 98 Report: Declarationsãæ¤ç´¢çµæãããã«åºã¦ãã¾ã (è¨äºå·ç彿) ã®ã§ãªã³ã¯ãéãããoperatorãã§ãã¼ã¸å
æ¤ç´¢ãã¾ãã
Any operator lacking a fixity declaration is assumed to be infixl 9 (See Section 3 for more on the use of fixities).The Haskell 98 Report: Declarations
ãªãã»ã©ãä½ãæ¸ããªãã£ããinfixl 9ã«ãªãã¨æ¸ãã¦ããã¾ãã
ããªãã¡ãä»åã®ã³ã¼ãã§ã¯
infixr 9 . infixl 9 ~> infixr 6 <> infixl 4 <*>
ãªã®ã§ã
(fromMaybe . show) <*> ((3 ~> "Fizz") <> (5 ~> "Buzz"))
ã®ããã«çµåãããã¨ãããã¡ãã¨åããã¾ããã ãã®FizzBuzzã®ã³ã¼ããæ¼ç®åã®çµåã®å¼·ãã峿¹ã«ã¤ãã¦ãã¦ã¨ã¦ã䏿ãã§ãã (ãã®æ¼ç®åã®å¼·ããè¦ãã¨ãã¯ãæ¬å½ã«ããã¼ãã¾ããªã¼ãã¨è¨ã£ã¦ã«ãã«ããã¦ãã¾ãã¾ãã)ã ããã¡ãã¨ãã®æå³ã¯ããªãã¨ãªãåä½ãã³ã¼ãã®è¦ãç®ããæ¨æ¸¬ããã®ã§ã¯ãªããæ ¹æ ãæã£ã¦çµè«ã¥ãã¦ãã¨ãããã¨ã§ãã æ¬å¼§ãæ¸ããã¦ããªãå¼ã®ä¸ã§æ¼ç®åã®æåã調ã¹ãã¨ãã¯ãã¾ãã¯çµåã®å¼·ãã調ã¹ãã®ããã¤ã³ãã§ãã
ãããã¾ãå³å´ã®åä½ãã確èªãã¦ããã¾ãããã
(3 ~> "Fizz") <> (5 ~> "Buzz")
FizzBuzzã®åºåçµæãã3 ~> "Fizz"ãããã¾ã§åä½ã¨åã確èªãã¦ãããã¨ããããã®é¢æ°ã¯
- 15ã®åæ°ãªã
Just "FizzBuzz" - 3ã®åæ°ãªã
Just "Fizz" - 5ã®åæ°ãªã
Just "Buzz" - ä¸è¨ã®ã©ãã§ããªããªã
Nothing
ã¨ãªã颿°ã§ãããã¨ãæ¨æ¸¬ããã¾ãã ããã¦ãå®éã«ãããªã®ã§ãï¼
Prelude Control.Monad Data.Monoid Data.Maybe> let f = (3 ~> "Fizz") <> (5 ~> "Buzz") Prelude Control.Monad Data.Monoid Data.Maybe> map f [1..20] :: [Maybe String] [Nothing,Nothing,Just "Fizz",Nothing,Just "Buzz",Just "Fizz",Nothing,Nothing,Just "Fizz",Just "Buzz",Nothing,Just "Fizz",Nothing,Nothing,Just "FizzBuzz",Nothing,Nothing,Just "Fizz",Nothing,Just "Buzz"]
ãã®ããã«3ã®åæ°ã®çµæã¨5ã®åæ°ã®çµæãçµåãã¤ã¤ãMaybeãè¿ãã¨ããã®ã¯ãç§ãcatMaybesã使ã£ãããããããã¡ããã¡ããã¦æ©ãã§çµå±ããããªãã£ãã¨ããã§ãã
ä¸ä½ãã®ã³ã¼ãã¯ã©ããªããªãã¯ã使ã£ã¦ããã®ã§ããããã
ããã«ã¯Monoidããã¾ã使ããã¦ãã¾ãã
注ç®ãã¹ãã¯è¨ãã¾ã§ããªãã(<>)ã¨ããæ¼ç®åã«ããã¾ãã
(3 ~> "Fizz") :: Integer -> Maybe String ã§ãããã¨ãããä»åã®ã³ã¼ãã§ã¯
(<>) :: (Integer -> Maybe String) -> (Integer -> Maybe String) -> (Integer -> Maybe String)
ã¨ãªã£ã¦ããã¯ãã§ãã
ããã§ãHoogleã§Monoidã¨å
¥åãã¦Data.Monoidã®ããã¥ã¡ã³ãã«é£ã³ã¾ãã
Monoidã¨ã¯ãä¸ã¤ã®äºé
æ¼ç®åã¨åä½å
ãæã¤ãããªä»£æ°çæ§é ã§ãã群ããéå
ã®åå¨ãæãããã®ã§ãã
è¦ããã«ã((||), False)ã¯Monoidã ã ((++), [])ã((+), 0)ãMonoidã§ãã
Monoidã«ã¤ãã¦ã¯ä»¥ä¸ã®è¨äºãåå¿è
ã«ãä¸å¯§ã«æ¸ããã¦ããã®ã§ãåèã«ãã¦ãã ããã
itchyny.hatenablog.com
ãã¦ãä»åã®Monoidã®instanceã¯ä½ã使ã£ã¦ããã®ã§ããããã
Monoidã®å®ç¾©ã¨(<>)ã¯æ¬¡ã®ããã«ãªã£ã¦ãã¾ãã
class Monoid a where mempty :: a mappend :: a -> a -> a (<>) :: Monoid m => m -> m -> m (<>) = mappend
ç¾å¨ã®ã³ã¼ãä¸ã®(<>)ã®åã¨ä¸ã®Monoidã®å®ç¾©ããã£ã¨è¦æ¯ã¹ãã¨ãMonoid (Integer -> Maybe String)ã使ã£ã¦ãããã¨ã«ãªãã¾ãã
ãããªã®è¦ããã¨ããã¾ããï¼ããã£ã颿°Monoidï¼ã¨ã³ã£ãããã¦Data.Monoidã®ããã¥ã¡ã³ãã確èªãã¾ãã¨ã確ãã«Monoid b => Monoid (a -> b)ã¨ãããã®ãããã¾ãã
Sourceãã¯ãªãã¯ãã¦ã³ã¼ãã確èªããã¨ã次ã®ããã«ãªã£ã¦ãã¾ãã
instance Monoid b => Monoid (a -> b) where mempty _ = mempty mappend f g x = f x `mappend` g x
ãªãã»ã©ããããããã颿°ãé©ç¨ãã2ã¤ãæ¼ç®åã«ãã¾ããããªé¢æ°ãè¿ããã§ãããmappendã®å®ç¾©ã¯ãã©ãã¨ãªãControl.Arrowã®(&&&)ãæãåºããã¾ãã
ããã¯æ¬å½ã«Monoidã«ãªã£ã¦ããã®ã§ããããã
ãã®å®ç¾©ã«å¾ãã¾ãã¨ãMonoid (a -> b)ã®memptyã¯\_ -> memptyã§ã (const memptyã§ã)ã
ãããä¸è¨ã§å®ç¾©ãããäºé
æ¼ç®åmappendã®åä½å
ã§ãããã¨ã確èªã§ããã°OKã§ãã
mappend (\_ -> mempty) g ==> \x -> ((\_ -> mempty) x) `mappend` g x ==> \x -> mempty `mappend` g x ==> \x -> g x (Monoid bã®æ§è³ªãã) ==> g mappend f (\_ -> mempty) ==> \x -> f x `mappend` ((\_ -> mempty) x) ==> \x -> f x `mappend` mempty ==> \x -> f x (Monoid bã®æ§è³ªãã) ==> f
ãã£ã¦\_ -> memptyã¯äºé
æ¼ç®åmappendã®åä½å
ã«ãªã£ã¦ãããã¨ã確ããããã¾ããã
å¾ã£ã¦ãããbãMonoidãªãMonoid (a -> b)ãä½ãããã¨ãåããã¾ããã
FizzBuzzã®ã³ã¼ãã§ä½¿ããã¦ãã(<>)ã¯ã
(3 ~> "Fizz") <> (5 ~> "Buzz")
次ã®ãããªåã§ããã
(<>) :: (Integer -> Maybe String) -> (Integer -> Maybe String) -> (Integer -> Maybe String)
ã§ãããa = Integerãb = Maybe Stringã¨ãªããããªMonoid (a -> b)ã使ããã¦ãã¾ãã
ããã§Monoid bã¨ãªããã¨ãè¦è«ããã¾ãããb = Maybe Stringã§ããããæ¬¡ã®ãããªinstanceã使ããã¾ãã
instance Monoid a => Monoid (Maybe a) where mempty = Nothing Nothing `mappend` m = m m `mappend` Nothing = m Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
Nothingãåä½å
ãæ¼ç®åã¯Justã®ä¸èº«ã«å¯¾ãã¦è¡ããã¾ãã
ã¤ã¾ããããããã¨ã§ããã
Prelude Data.Monoid> Just "Fizz" <> Just "Buzz" Just "FizzBuzz" Prelude Data.Monoid> Just "Fizz" <> Nothing Just "Fizz" Prelude Data.Monoid> Nothing <> Just "Buzz" Just "Buzz" Prelude Data.Monoid> Nothing <> Nothing Nothing
ããããè¬ãè§£ãã¦ãã¾ããã ããä¸åº¦ãã£ã¨ã³ã¼ããè¦ã¤ãã¦
(3 ~> "Fizz") <> (5 ~> "Buzz") instance Monoid b => Monoid (a -> b) where mappend f g x = f x `mappend` g x
é çªã«ã©ã®æ§è³ªã使ã£ã¦ããã確èªããªããæ¸ãæãã¦ããã¾ã (åã®è¯ã人ã¯åãã£ãã¨ããã§æ¢ãã¦ããã§ãã)ã
(3 ~> "Fizz") <> (5 ~> "Buzz") ==> (\n -> if n `mod` 3 == 0 then Just "Fizz" else Nothing) <> (\n -> if n `mod` 5 == 0 then Just "Buzz" else Nothing) ==> \n -> ((if n `mod` 3 == 0 then Just "Fizz" else Nothing) <> (if n `mod` 5 == 0 then Just "Buzz" else Nothing)) (颿°Monoidã®mappend) ==> \n -> (if n `mod` 3 == 0 && n `mod` 5 == 0 then Just "Fizz" <> Just "Buzz" else if n `mod` 3 == 0 && !(n `mod` 5 == 0) then Just "Fizz" <> Nothing else if !(n `mod` 3 == 0) && n `mod` 5 == 0 then Nothing <> Just "Buzz" else Nothing <> Nothing) (ifãå±é) ==> \n -> (if n `mod` 3 == 0 && n `mod` 5 == 0 then Just "FizzBuzz" else if n `mod` 3 == 0 && !(n `mod` 5 == 0) then Just "Fizz" else if !(n `mod` 3 == 0) && n `mod` 5 == 0 then Just "Buzz" else Nothing) (Maybe Monoidã«ããã¦Nothingã¯åä½å )
ãã£ã¨ããã®é¢æ°ãæå³ããåä½ããããã¨ã確èªã§ãã¾ãã (ifã¯å±éããã¨ãã¤ã¡ã¼ã¸ã§ãããããã§ã)ã å°ãã¾ã¨ãã¾ãã¨ã
- ãã®
(<>)ã¯3ã¤ã®Monoidã使ããã¦ãã - ä¸ã¤ç®ã¯
instance Monoid [a]:((++), [])ãããã®ãããã§"Fizz" <> "Buzz"ã"FizzBuzz"ã¨ãªãã - äºã¤ç®ã¯
instance Monoid a => Monoid (Maybe a)ãåä½å ã¯NothingãJust "Fizz" <> Just "Buzz"ãJust "FizzBuzz"ã«ãªããNothingãåä½å ãªã®ã§ãJust "Fizz" <> Nothing == Just "Fizz"ã«ãªãã - ä¸ã¤ç®ã¯
instance Monoid b => Monoid (a -> b)ãåä½å ã¯\_ -> memptyã3ã®åæ°ã«å¯¾ãã颿°ã¨ã5ã®åæ°ã«å¯¾ãã颿°ã(<>)ã§çµåãã¦ããããã®çµæããã¾ããã£ã¤ãããããªé¢æ°ãä½ããã¨ãã§ããã
ããªãå·§å¦ã«Monoidã使ããã¦ãããã¨ãåããã¾ãã
æå¾ã«æ®ã£ãã®ã¯ã(<*>)ã¨ããæ¼ç®åã§ãã
(fromMaybe . show) <*> ((3 ~> "Fizz") <> (5 ~> "Buzz"))
æ¼ç®åã®å·¦è¾ºã¯æ¬¡ã®ãããªåã§ãã®ã§ã
Prelude Control.Monad Data.Monoid Data.Maybe> :t fromMaybe . show fromMaybe . show :: Show a => a -> Maybe String -> String Prelude Control.Monad Data.Monoid Data.Maybe> :t fromMaybe . show :: Integer -> Maybe String -> String fromMaybe . show :: Integer -> Maybe String -> String :: Integer -> Maybe String -> String
ãã®(<*>)æ¼ç®åã®ç¹åãããåã¯æ¬¡ã®ããã«ãªãã¯ãã§ãã
Prelude Control.Monad Data.Monoid Data.Maybe> :t (<*>) :: (Integer -> Maybe String -> String) -> (Integer -> Maybe String) -> Integer -> String (<*>) :: (Integer -> Maybe String -> String) -> (Integer -> Maybe String) -> Integer -> String :: (Integer -> Maybe String -> String) -> (Integer -> Maybe String) -> Integer -> String
ãã¡ãã¨åãåãã¾ãããã
ãã¦ã(<*>)ã¯Applicativeã®æ¼ç®åã§ããããããããµããªåã«ãªãinstanceã¯ä½ã ããã¨èª¿ã¹ã¾ãã
(<*>)ã®éåãããåã¯
Prelude Control.Monad Data.Monoid Data.Maybe> :t (<*>) (<*>) :: Applicative f => f (a -> b) -> f a -> f b
ã§ãã®ã§ãä»å使ããã¦ããåã¨ç¨ã¿ãªããæ¬¡ã®ããã«å½ã¦ã¯ãã¦ã¿ã¾ãã
f (a -> b) === Integer -> Maybe String -> String f a === Integer -> Maybe String f b === Integer -> String
ãªãããããªäºæããã¾ããâ¦ é¢æ°ããªâ¦
Hoogleã§ãã®æ¼ç®åã調ã¹ã¦ãControl.Applicativeã®ããã¥ã¡ã³ãã«é£ã³ã¾ãã
ããããã¨ãinstance Applicative ((->) a)ã¨ããããã£ã½ãinstanceãè¦ã¤ããã®ã§ãæ
ã¦ã¦ç´ã¨éçãåã£ã¦åãåãã確ããã¾ãã
f (a -> b) === ((->) r) (a -> b) === r -> a -> b === Integer -> Maybe String -> String f a === ((->) r) a === r -> a === Integer -> Maybe String f b === ((->) r) b === r -> b === Integer -> String a === Maybe String b === String r === Integer
åã¯åãã¾ããã
次ã«ãã®instanceã®Sourceãè¦ã«è¡ãã¾ãã
instance Applicative ((->) a) where pure = const (<*>) f g x = f x (g x)
ãªãã ããã¯â¦
f xã«g xãé©ç¨ããã¨ãè¨ã£ã¦ãã¾ããâ¦
ã¤ã¾ãä»åã®å ´åã¯
(fromMaybe . show) <*> ((3 ~> "Fizz") <> (5 ~> "Buzz"))
ãªã®ã§ãä¸çæ¸å½å¤å½¢ãã¦ããã¨
(fromMaybe . show) <*> ((3 ~> "Fizz") <> (5 ~> "Buzz")) ==> (\f g x -> f x (g x)) (fromMaybe . show) ((3 ~> "Fizz") <> (5 ~> "Buzz")) ==> (\g x -> (fromMaybe . show) x (g x)) ((3 ~> "Fizz") <> (5 ~> "Buzz")) ==> \x -> fromMaybe (show x) (((3 ~> "Fizz") <> (5 ~> "Buzz")) x)
ãªãã»ã©ãããåããã¾ãããã
æåã®fizzbuzzããã®å½¢ã§æ¸ãã¦ã¿ã¾ãã
fizzbuzz n = let (d ~> s) n = s <$ guard (n `mod` d == 0) in fromMaybe (show n) (((3 ~> "Fizz") <> (5 ~> "Buzz")) n)
ããã¾ã§æ¥ããèªãã¾ããï¼
ãã¨ã¯fromMaybeã¨ãã颿°ãç¥ã£ã¦ãããã©ããã¨ããã ãã§ãã
Hoogleã§fromMaybeãæ¤ç´¢ããData.Maybeã®ããã¥ã¡ã³ãã«é£ã³ã¾ãã
fromMaybe :: a -> Maybe a -> aThe fromMaybe function takes a default value and and Maybe value. If the Maybe is Nothing, it returns the default values; otherwise, it returns the value contained in the Maybe.The base package: Data.Maybe
ã¤ã¾ããããã©ã«ããæå®ãã¦Justããå®å
¨ã«åãåºã颿°ã¨ããããã§ãã
念ã®ããã«Sourceãè¦ã«è¡ãã¾ãã
fromMaybe :: a -> Maybe a -> a fromMaybe d x = case x of {Nothing -> d;Just v -> v}
ã³ã¼ãã¯ã¨ã¦ãç°¡æ½ã§ã確ãã«Nothingãªãããã©ã«ããè¿ãã¦ããã§ãªããªãJustãå¤ãã¦ãã¾ãã
ä»FizzBuzzã®ã³ã¼ãã¯
fromMaybe (show n) (((3 ~> "Fizz") <> (5 ~> "Buzz")) n)
ã¨ãªã£ã¦ãã¾ããfromMaybeã®ç¬¬äºå¼æ°ãJust "FizzBuzz"ã¾ãã¯Just "Fizz"ãJust "Buzz"ããã¦Nothingãè¿ããã¨ãæãåºãã¨ãJustããåãåºãã¤ã¤Nothingã®ã¨ãã¯æ°åããã®ã¾ã¾è¡¨ç¤ºããshow nã¨ãªã£ã¦ãããã¨ãåããã¾ãã
- æ¼ç®åãåºã¦ãããçµåã®å¼·ãã確èªããããçµåã®å¼·ãããã¡ããæå®ããªããã°ã
infixl 9ã«ãªãã Monoid䏿®µæ§ããinstance Monoid b => Monoid (a -> b)ã®åä½å ã¯\_ -> memptyã2ã¤ã®é¢æ°ã®è¿ãå¤ãåãåã§ãã¤Monoidãªãã颿°ãã¡ããã¾ãmappendãããã¨ãã§ãããinstance Applicative ((->) a)ã§ã¯(<*>) f g x = f x (g x)ã«ãªã£ã¦ããã
åãã³ã¼ããæ¸ãã¦ã¿ãã
ããã¾ã§ã¯ããã§ã«ããã³ã¼ããèªã¿è§£ãæ¹æ³ã説æãã¦ãã¾ããã ãããããããæ¸ãã人ã¯ãã©ã®ããã«ãã®ã³ã¼ããæ¸ããã®ã§ããããã ãã£ã¨ç§ãã¡ã«ãçè§£ã§ãã試è¡é¯èª¤ã§ãåãã³ã¼ããçµã¿ç«ã¦ããã¨ãã§ããã¯ãã§ãã ãããæ¸ããããã«ã¯ã©ããããã¨ãã§ããã°ããããã©ããããã¨ã¯ç¥ã£ã¦ããªããã°ãããªããã確ããã¦ã¿ã¾ãããã
ã¾ããfizzbuzz颿°ã¯Integer -> Stringãä½ããã¨ã«ãã¾ããã (ãªãªã¸ãã«ã¯ãããmapãããã®ã§ã)ã
main :: IO () main = mapM_ (print . fizzbuzz) [1..100] fizzbuzz = ...
å¾ã§printã¯putStrLnã«ãã¾ãããã³ã¼ããæ¸ãã¦ããéä¸ã¯é¢åãªã®ã§æåã¯printã¨æ¸ãã¦ããã¾ãã
ã¾ãç°¡åãªãã®ãæ¸ãã¦ã¿ã¾ãã
fizzbuzz n | n `mod` 15 == 0 = "FizzBuzz" | n `mod` 3 == 0 = "Fizz" | n `mod` 5 == 0 = "Buzz" | otherwise = show n
å®è¡ãããæ¬¡ã®ããã«ãªãã¾ãã
"1" "2" "Fizz" "4" "Buzz" "Fizz" "7" "8" "Fizz" "Buzz" "11" "Fizz" "13" "14" "FizzBuzz" "16" "17" "Fizz" "19" "Buzz" ...
åä½ã¯å¤§ä¸å¤«ã§ãã
ãã¦ãä½åº¦ãmodã¨æ¸ãã¦ããã®ã§ã颿°ã«ãããã§ããã
ã¾ããmod 3ã®è¨ç®çµæã¨mod 5ã®è¨ç®çµæãä½ã¨ããã¦ã¾ã¨ãããã§ãã
3ã®åæ°ãªãJust æååãè¿ããããã§ãªããªãNothingãè¿ãããããªé¢æ°ãä½ã£ã¦ã¿ã¾ãããã
fizzbuzz n = (show n, f n 3 "Fizz", f n 5 "Buzz") f n d s = if n `mod` d == 0 then Just s else Nothing
å®è¡ãã¦ã¿ã¾ãã
("1",Nothing,Nothing) ("2",Nothing,Nothing) ("3",Just "Fizz",Nothing) ("4",Nothing,Nothing) ("5",Nothing,Just "Buzz") ("6",Just "Fizz",Nothing) ("7",Nothing,Nothing) ("8",Nothing,Nothing) ("9",Just "Fizz",Nothing) ("10",Nothing,Just "Buzz") ("11",Nothing,Nothing) ("12",Just "Fizz",Nothing) ("13",Nothing,Nothing) ("14",Nothing,Nothing) ("15",Just "Fizz",Just "Buzz") ("16",Nothing,Nothing) ("17",Nothing,Nothing) ("18",Just "Fizz",Nothing) ("19",Nothing,Nothing) ("20",Nothing,Just "Buzz") ...
ã¡ããã¨ã§ãã¦ãã¾ããã
modãä¸ç®æã«ãªã£ã¦ããæãã§ãã
ãããã®çµæãéç´ãã¦ããã¾ãããã ã¾ã3ã®åæ°ãã¤5ã®åæ°ãããªãã¡
("15",Just "Fizz",Just "Buzz")
ã®äºã¤ç®ã¨ä¸ã¤ç®ãJust "FizzBuzz"ã«ãããã¨èãã¾ãã
ã©ã¡ãã䏿¹ãNothingã ã£ãã仿¹ãæ¡ç¨ãã⦠ããã¯Monoidã ã¨æ°ãä»ãã¾ãã
Monoidã®æ¼ç®å(<>)ã使ãããã¨ã確èªãã¾ãã
$ ghci GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help Prelude> import Data.Monoid Prelude Data.Monoid> Just "Fizz" <> Just "Buzz" Just "FizzBuzz" Prelude Data.Monoid> Just "Fizz" <> Nothing Just "Fizz" Prelude Data.Monoid> Nothing <> Just "Buzz" Just "Buzz" Prelude Data.Monoid> Nothing <> Nothing Nothing
ããããã§ããï¼ æ©éãã®æ¼ç®åã使ã£ã¦ã¿ã¾ãã
fizzbuzz n = (show n, f n 3 "Fizz" <> f n 5 "Buzz")
("1",Nothing) ("2",Nothing) ("3",Just "Fizz") ("4",Nothing) ("5",Just "Buzz") ("6",Just "Fizz") ("7",Nothing) ("8",Nothing) ("9",Just "Fizz") ("10",Just "Buzz") ("11",Nothing) ("12",Just "Fizz") ("13",Nothing) ("14",Nothing) ("15",Just "FizzBuzz") ("16",Nothing) ("17",Nothing) ("18",Just "Fizz") ("19",Nothing) ("20",Just "Buzz") ...
ãã¾ããã£ã¦ã¾ãï¼
ããã¦ãå³å´ãNothingã®æã«ã®ã¿å·¦å´ãæ¡ç¨ãããè¯ãããã§ãã
Justããä¸èº«ãåãåºãã¤ã¤å®å
¨ãªâ¦ fromMaybeã§ããï¼
fizzbuzz n = fromMaybe (show n) (f n 3 "Fizz" <> f n 5 "Buzz")
"1" "2" "Fizz" "4" "Buzz" "Fizz" "7" "8" "Fizz" "Buzz" "11" "Fizz" "13" "14" "FizzBuzz" "16" "17" "Fizz" "19" "Buzz" ...
ãã£ãã¼ï¼ ãã¾ãããã¾ããã
ããããã¯ãæ´ã«ã³ã¼ããé£èªåæ´ç·´ããã¦ããã¾ãã
f n d s = if n `mod` d == 0 then Just s else Nothing
ã¾ãif .. then .. elseãè¾ãããã§ããã
BoolããMaybe Stringã«ãªããããªé¢æ°ããããªãã®ããã¾ããã£ãã
åã§ Bool -> Maybe Stringããã Bool -> Maybe a ã®ã»ããè¯ãããããªã¨æã£ã¦Hoogleã§æ¤ç´¢ãã¾ãã
Justãéããreturnãéã⦠第ä¸å¼æ°ãBoolã®ãã¤ã¯â¦ fromBooléã⦠ããguardï¼ãããªãã ã£ãâ¦
guard :: MonadPlus m => Bool -> m ()
ã¨æã£ã¦ãå®ç¾©ãè¦ã«è¡ãã¾ã (ä»åãã¾ãã¾Maybe aã§ããããã¦ãã¾ãã¾ããããæãããã«è¦ã¤ãããªãã¨ãã¯ã©ãã©ãä¸è¬åããã¦Bool -> m aã®ããã«æ¤ç´¢ãã¾ã)ã
guard :: Alternative f => Bool -> f ()guard b is pure () if b is True, and empty if b is False.The base package: Control.Monad
instance Applicative Maybeã調ã¹ã¤ã¤ãghciã§ç¢ºèªãã¦ã¿ã¾ãã
Prelude Control.Monad> guard True :: Maybe () Just () Prelude Control.Monad> guard False :: Maybe () Nothing
ãªãã»ã©ã
f n d s = if guard (n `mod` d == 0) == Just () then Just s else Nothing
Just ()ãªãJust sãNothingãªãNothingãªã®ã§ãfmapã ã¨ããã«æ°ãä»ãã¾ãã
f n d s = fmap (const s) (guard (n `mod` d == 0))
"1" "2" "Fizz" "4" "Buzz" "Fizz" "7" ...
guardã使ã£ã¦ifãæ¶ãã¾ããï¼
ããã¦ãconstãã¦fmap⦠fmap . const⦠(<$)ã§ããï¼
ããã¯æµç³ã«ç¥ã£ã¦ãããªãã¨æ°ãã¤ãã¾ããã
å°ãåä½ã確èªãã¦ããã¾ãããã
Prelude> 1 <$ Just 0 Just 1 Prelude> 1 <$ Nothing Nothing Prelude> 1 <$ [1..5] [1,1,1,1,1] Prelude> 1 <$ Left 0 Left 0 Prelude> 1 <$ Right 0 Right 1
ãµããµãããªãã»ã©ã
Functorç´ æ´ãããã§ããã
ãã®æ¼ç®åã使ãã¨ã次ã®ããã«ãªãã¾ããã
f n d s = s <$ guard (n `mod` d == 0)
ã§ãã¾ãããï¼
次ã¯ãfizzbuzz颿°æ¬ä½ãpoint-freeã¹ã¿ã¤ã«ã«å¤å½¢ãã¾ãããã
fizzbuzz n = fromMaybe (show n) (f n 3 "Fizz" <> f n 5 "Buzz")
弿°ã®nãæ¶ãããã§ãã
ã¾ããå¾ãå´ã®ã¨ããã§nã第1弿°ã«æ¥ã¦ããã®ãé£ããã®ã§ãæå¾ã«æ¥ãããã«fã夿´ãã¾ã
fizzbuzz n = fromMaybe (show n) (f 3 "Fizz" n <> f 5 "Buzz" n) f :: Integer -> String -> Integer -> Maybe String f d s n = s <$ guard (n `mod` d == 0)
fã®åãæ¸ãã¦ã¿ã¾ãããf 3 "Fizz"ã¯Integer -> Maybe Stringã§ããã
ããã§ã颿°ã®Monoidãæãåºãã¾ããããããã¯ãç¥ã£ã¦ããªãã¨ã§ãã¾ãããã
instance Monoid b => Monoid (a -> b) where mempty _ = mempty mappend f g x = f x `mappend` g x
ã¾ãã« f 3 "Fizz" n <> f 5 "Buzz" n ã®é¨åããã®å½¢ã«ãªã£ã¦ãã¾ãï¼
ãã£ã¦ã次ã®ããã«ãæ¸ãã¾ãã
fizzbuzz n = fromMaybe (show n) ((f 3 "Fizz" <> f 5 "Buzz") n)
show nã®nãæ·±ãã¨ããã«ããã®ã§ãå°ãå¤å½¢ãã¾ãã
fizzbuzz n = ((fromMaybe . show) n) ((f 3 "Fizz" <> f 5 "Buzz") n)
nãäºå使ããã¦ãã¾ããf n (g n)ã®å½¢ã§ãã
ãã¼ãã¨èãã¦ãApplicative ((->) a)ãMonad ((->) r)ãªã©ã調ã¹ã¾ãã
instance Applicative ((->) a) where pure = const (<*>) f g x = f x (g x) instance Monad ((->) r) where return = const f >>= k = \r -> k (f r) r
ä»åã¯Applicativeã®æ¹ã§ããã
fizzbuzz n = ((fromMaybe . show) <*> (f 3 "Fizz" <> f 5 "Buzz")) n
æå¾ã«Î·å¤æã§ãï¼
fizzbuzz = (fromMaybe . show) <*> (f 3 "Fizz" <> f 5 "Buzz")
ããã¾ããï¼point-freeã¹ã¿ã¤ã«ã«ãªãã¾ããï¼
颿°fãfizzbuzzã®ä¸ã«å
¥ãã¦
fizzbuzz = let f d s n = s <$ guard (n `mod` d == 0) in (fromMaybe . show) <*> (f 3 "Fizz" <> f 5 "Buzz")
ããã£ã½ãæ¼ç®åã«æ¸ãæãã¤ã¤ãæãæãæ¬å¼§ãå¤ããprintãputStrLnã«ããã宿ã§ãï¼
main :: IO () main = mapM_ (putStrLn . fizzbuzz) [1..100] fizzbuzz :: Integer -> String fizzbuzz = let (d ~> s) n = s <$ guard (n `mod` d == 0) in fromMaybe . show <*> 3 ~> "Fizz" <> 5 ~> "Buzz"
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz ...
ãã£ãã¼ï¼ï¼ï¼ ãªãã¨ãå ã®ã³ã¼ããåæ§ç¯ãããã¨ãã§ãã¾ããï¼
æ°åã¨æ ¹æ§ã¨ããã¤ãã®ç¥èãå¿ è¦ã§ããã
- ã¨ã«ããããã°ããã¨ã«ããpoint-freeã¹ã¿ã¤ã«ã
- å°ã£ã¦ã
Arrowã«é ¼ããããªããã¨ããããMonadã¨ãApplicativeãªã©ããããã£ã½ãã®ãæ¢ãã((->) a)ã«æ³¨ç®ãããã Monoid便å©ãè¶ ä¾¿å©ã便å©ãããã
ã¾ã¨ã
Monoidã»Functorã»Applicativeã»Alternativeãããã¦Monadã åã¯ã©ã¹ã¯Haskellã®ç¹å¾´çãªæ©è½ã§ãããã¨ã¦ã便å©ãªãã®ã§ãã åã¯ã©ã¹ã¯æã ã®ã³ã¼ããéåããã¾ãã³ã¼ããæ¸ãã¨ãã«ã¯ã©ãããæ§é ã®ã©ãããæ§è³ªã使ã£ã¦ããããæèããã¦ããã¾ãã ç§ã¯Haskellã®æ§ã ãªæ©è½ã«é äºããã¦ä½¿ã£ã¦ãã¾ãããåã¯ã©ã¹ã®æ©è½ããããªãã£ããããã¾ã§æ¹ããããã¨ã¯ãªãã£ãããããã¾ããã
point-freeã¹ã¿ã¤ã«ã¯å¸¸ã«ãããã®ã§ã¯ããã¾ããã æã«ã¯ã³ã¼ããé£è§£ã«ããèªããªããã®ã«ãã¦ãã¾ãã¾ãã ç§ã¯ä¸ææArrowã®combinatorã使ã£ãpoint-freeã¹ã¿ã¤ã«ã«æ²¡é ããææãããã¾ãããããã°ãããã¦ç±ãå·ãã¦ãã¾ããæ®ã£ãã®ã¯å ¨ãèªããªãé£è§£ãªã³ã¼ãã°ããã§ããã
ãããããã¡ããç©æ¥µçã«ä½¿ãã¹ãã±ã¼ã¹ã ã£ã¦å¤ã
ããã¾ãã
\x -> f (g x)ãããf . gã®ã»ããèªã¿ããããã2ã¤ã®é¢æ°ãé çªã«é©ç¨ãããã¨ããæå³ãã¯ã£ãããã¦ãã¾ãã
ã¾ããdo { a <- m1; b <- m2; return (f a b) }ããã f <$> m1 <*> m2 ã®ã»ãããæ¬å½ã«ä½ãããããã®ãã¨ãããã¨ã«éä¸ãã¦ã³ã¼ããæ¸ããã¨ãã§ãã¾ãã
ãã¡ãã¡ case ... of ã使ã£ã¦ããã¨ãããã Alternative Maybe ã® (<|>) ã§ãµã©ãã¨æ¸ããã¨ãã¯å¿«æã§ãã
åã¯ã©ã¹ã®ã¡ã½ãããæå³ã®ããç¨éã§ä½¿ããã³ã¼ããç°¡æ½ã«ãªããªãã°ãããã¯æ¨å¥¨ããã¦ããã§ãããã
è¤éãªã³ã¼ããè§£èªãã¦ããã®ã¯ãã¨ã¦ã楽ããããºã«ã§ãã æã«ã¯ä¾¿å©ãªinstanceãçºè¦ããããåã¯ã©ã¹ã¸ã®çè§£ãæ´ã«æ·±ã¾ããã¨ãããã¾ãã æ½è±¡çãªé«é颿°ãããã¾ã§èªå¨ã«æ±ããè¨èªã¯ä»ã«ã¯ãªãã¨æãã¾ãã æå·§çããã¦å®éã«ã¯æ¸ããªããå½¹ã«ç«ããªããªã©ã¨è¨ããããã¾ã«ã¯é ã®ä½æã¨æã£ã¦ä»çµã¿ã調ã¹ã¦ã¿ã¦ã¯ãããã§ããããã