wvogel日記

自分用の技術備忘録が多めです.

Applicative

import Control.Applicative

main = do  a <- getLine
           b <- getLine
           print $ f a b

f :: String -> String ->Int
f a b = (+) (read a) (read b)

これは勿論動きます


では、ghci上で上記のようにfを宣言し、Control.Applicativeモジュールをインポートしたうえで

f <$> getLine <*> getLine

とするとやっぱり動いた!
やったね

しかし、

import Control.Applicative
    
main = print $ f <$> getLine <*> getLine

f :: String -> String ->Int
f a b = (+) (read a) (read b)

とすると動かない。
どうも、print以下の型がいけないようです
そこで、<$>などの型を確認。

 (<$>) :: (a -> b) -> m a -> m b

ですから、これは純粋関数にモナドに内包された値を渡し、
モナドに内包した状態で返ってきます。
あたりまえですね、<$>はfmapのことですから。
で、今使用しているgetLineはIOモナドなので、
IO Intの形から、Intを取りだしてやればいいわけです。

import Control.Applicative

main = f <$> getLine <*> getLine
        >>= \x -> print x

f :: String -> String ->Int
f a b = (+) (read a) (read b)


Foreignモジュールを利用して

import Control.Applicative
import Foreign.Marshal

main = print $ unsafeLocalState $ f <$> getLine <*> getLine

f :: String -> String ->Int
f a b = (+) (read a) (read b)

としたり。


というけで、do記法からdoを消してやることが出来ました!<*>でさらに繋いでいくことも出来るでしょう