gpt4 book ai didi

haskell - 从 monad 中取出 monadic 函数

转载 作者:行者123 更新时间:2023-12-02 14:56:06 26 4
gpt4 key购买 nike

Haskell 具有函数 join,它“运行”单子(monad)内部的单子(monad)操作:

join :: Monad m => m (m a) -> m a
join m = m >>= \f -> f

我们可以用一个参数为一元函数编写一个类似的函数:

join1 :: Monad m => m (a -> m b) -> (a -> m b)
join1 m arg1 = m >>= \f -> f arg1

对于两个参数:

join2 :: Monad m => m (a -> b -> m c) -> (a -> b -> m c)
join2 m arg1 arg2 = m >>= \f -> f arg1 arg2

是否可以编写一个通用函数joinN,它可以处理具有 N 个参数的一元函数?

最佳答案

如果你真的愿意的话,你可以做一些相当丑陋的事情。

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}

import Control.Monad (join, liftM)

class Joinable m z | z -> m where
joins :: m z -> z

instance Monad m => Joinable m (m a) where
joins = join

instance (Monad m, Joinable m z) => Joinable m (r -> z) where
joins m r = joins (liftM ($ r) m)

但是,正如您所看到的,这依赖于一些不稳定的类型类魔法(特别是令人羡慕的UndecidableInstances)。编写所有实例 join1...join10 并直接导出它们可能会更好(虽然看起来很丑)。这也是 base 库中建立的模式。

值得注意的是,在这种制度下推理不会很好地发挥作用。例如

λ> joins (return (\a b -> return (a + b))) 1 2
Overlapping instances for Joinable ((->) t0) (t0 -> t0 -> IO t0)
arising from a use of ‘joins’
Matching instances:
instance Monad m => Joinable m (m a)
-- Defined at /Users/tel/tmp/ASD.hs:11:10
instance (Monad m, Joinable m z) => Joinable m (r -> z)
-- Defined at /Users/tel/tmp/ASD.hs:14:10

但是如果我们给我们的参数一个明确的类型

λ> let {q :: IO (Int -> Int -> IO Int); q = return (\a b -> return (a + b))}

那么它仍然可以像我们希望的那样工作

λ> joins q 1 2
3

出现这种情况是因为仅使用类型类就很难指示您是要对函数链的最终返回类型中的 monad m 进行操作,还是对 monad (->) 进行操作r 是函数链本身。

关于haskell - 从 monad 中取出 monadic 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28203347/

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