gpt4 book ai didi

haskell - 带有多个参数的绑定(bind)函数

转载 作者:行者123 更新时间:2023-12-02 01:51:52 27 4
gpt4 key购买 nike

在阅读了一些非常基本的 haskell 后,我现在知道如何使用 bind 来“链接”单子(monad)操作,例如:

echo = getLine >>= putStrLn

(>>=) 运算符以这种方式非常方便,但是如果我想链接采用多个参数的单子(monad)操作(或仿函数)怎么办?

鉴于 (>>=)::m a -> (a -> m b) -> m b 似乎 (>>=) 只能提供一个论证。

例如,writeFile 采用两个参数(FilePath 和内容)。假设我有一个返回 FilePath 的单子(monad)操作,以及另一个返回要写入的 String 的操作。如何在不使用 do 符号的情况下,以通用方式将它们与 writeFile 结合起来?

有没有类型为:m a -> m b -> (a -> b -> m c) -> m c 的函数可以做到这一点?

最佳答案

TL;博士:

writeFile <$> getFilename <*> getString >>= id   :: IO ()

Monad 是适用的

自 ghc 7.10 起,每个 Monad(包括 IO )也是一个 Applicative,但即使在此之前,您也可以使用等效的方法从任何 Monad 中创建一个 Applicative

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)

当然还有IO是一个仿函数,但是 Control.Applicative给你<$>可以定义为f <$> mx = fmap f mx .

使用 Applicative 来使用接受任意数量参数的函数

<$><*>让你使用纯函数 f通过应用/单子(monad)计算产生的参数,所以如果 f :: String -> String -> BoolgetFileName, getString :: IO String然后

f <$> getFileName <*> getString :: IO Bool

类似地,如果 g :: String -> String -> String -> Int ,然后

g <$> getString <*> getString <*> getString :: IO Int

来自 IO (IO ())IO ()

这意味着

writeFile <$> getFilename <*> getString :: IO (IO ())

但是你需要 IO () 类型的东西,不是IO (IO ()) ,所以我们需要使用 join :: Monad m => m (m a) -> m aXeo's comment ,或者我们需要一个函数来获取一元结果并运行它,即 (IO ()) -> IO () 类型来绑定(bind)它。那将是 id那么,我们可以这样做

join $ writeFile <$> getFilename <*> getString :: IO ()

writeFile <$> getFilename <*> getString >>= id :: IO ()

关于haskell - 带有多个参数的绑定(bind)函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22115472/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com