gpt4 book ai didi

haskell - 单子(monad)内的值,嵌套在数据结构中?

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

假设在 Haskell 程序中我有一些数据,其类型如下:

  • IO [ IO(整数、字符串、整数)]
  • IO [ (Int, String, IO Int) ]
  • [ (Int, String, IO Int) ]

但我有应该在 [ (Int, String, Int) ] 上运行的纯函数。看来我必须笨拙地从 IO monad 中删除内部值,直到我得到类似 IO [ (Int, string, Int) ] 的东西,然后(从 IO monad 内部)应用纯函数。我想没有简单的预定义方法可以做到这一点?有什么东西可以将整个数据结构提升为一个单子(monad),将所有内部类型转换为纯类型? (那会很方便!)

最佳答案

您可以使用 Control.Monad 中的 liftM* 函数模块,或 applicativesliftA* 函数.

liftM 允许您提升纯函数以在 Monad 内工作,例如:

ghci> let s = return "Hello" :: IO String
ghci> liftM reverse s
"olleH"

这样您就不必到处手动编写“s >>=\x -> return (reverse x)”之类的内容。

尽管如此,这对您的 [(String, Int, IO Int)] 示例没有帮助,如果您拥有的纯函数处理 [(String, Int, Int)]。由于元组中的第三个元素实际上不是 Int

在这种情况下,我建议首先编写一个函数 [(String, Int, IO Int)] -> IO [(String, Int, Int)] 并应用提升的纯功能。

<小时/>

这是我能想到的最通用的函数:

conv :: Monad m => (f (m a) -> m (f a)) -> [f (m a)] -> m [f a]
conv f = sequence . map f

你可以这样调用它:

liftTrd :: Monad m => (a, b, m c) -> m (a, b, c)
liftTrd (x, y, mz) = mz >>= \z -> return (x, y, z)

conv liftTrd [("hi", 4, return 2)] :: IO [(String, Int, Int)]

只有当您有一个位于类型深处的单个 monad 时,此函数才会起作用。如果您有多个,我认为您应该认真考虑您使用的类型,看看是否不能使其变得更简单。

关于haskell - 单子(monad)内的值,嵌套在数据结构中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1160702/

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