在阅读了一些非常基本的haskell后,我知道如何使用bind "链接"monadic动作,如:
echo = getLine >>= putStrLn
Run Code Online (Sandbox Code Playgroud)
(>>=) 运算符在这种方式下非常方便,但是如果我想链接带有多个参数的monadic动作(或仿函数)呢?
鉴于(>>=) :: m a -> (a -> m b) -> m b它似乎(>>=)只能提供一个论点.
例如,writeFile接受两个参数(a FilePath和内容).假设我有一个返回a的monadic动作FilePath,以及另一个返回String写入的动作.如何在writeFile不使用do-notation的情况下将它们组合在一起,但是以一般方式?
是否有任何类型的功能: m a -> m b -> (a -> b -> m c) -> m c可以做到这一点?
And*_*ewC 14
TL; DR:
writeFile <$> getFilename <*> getString >>= id :: IO ()
Run Code Online (Sandbox Code Playgroud)
由于ghc 7.10每个Monad(包括IO)也是一个申请人,但即便在此之前,你可以使用相当于
import Control.Applicative -- not needed for ghc >= 7.10
instance Applicative M where
pure x = return x
mf <*> mx = do
f <- mf
x <- mx
return (f x)
Run Code Online (Sandbox Code Playgroud)
当然IO是一个仿函数,但Control.Applicative给你<$>可以定义为f <$> mx = fmap f mx.
<$>并且<*>让你使用纯函数f而不是Applicative/Monadic计算产生的参数,所以if f :: String -> String -> Bool和getFileName, getString :: IO Stringthen
f <$> getFileName <*> getString :: IO Bool
Run Code Online (Sandbox Code Playgroud)
同样,如果g :: String -> String -> String -> Int,那么
g <$> getString <*> getString <*> getString :: IO Int
Run Code Online (Sandbox Code Playgroud)
IO (IO ())到IO ()这意味着
writeFile <$> getFilename <*> getString :: IO (IO ())
Run Code Online (Sandbox Code Playgroud)
但是你需要一些类型的东西IO (),不是IO (IO ()),所以我们需要join :: Monad m => m (m a) -> m a像在Xeo的注释中一样使用,或者我们需要一个函数来获取monadic结果并运行它,即类型(IO ()) -> IO ()绑定它.那就是id,所以我们可以做到
join $ writeFile <$> getFilename <*> getString :: IO ()
Run Code Online (Sandbox Code Playgroud)
要么
writeFile <$> getFilename <*> getString >>= id :: IO ()
Run Code Online (Sandbox Code Playgroud)
为此使用do符号要容易得多,而不是要求组合器
action1 :: MyMonad a
action2 :: MyMonad b
f :: a -> b -> MyMonad c
do
x <- action1
y <- action2
f x y
Run Code Online (Sandbox Code Playgroud)
此类型检查:
import System.IO
filepath :: IO FilePath
filepath = undefined
someString :: IO String
someString = undefined
testfun = filepath >>= (\fp ->
someString >>= (\str ->
writeFile fp str ))
Run Code Online (Sandbox Code Playgroud)
但我觉得使用 do 表示法更具可读性。