2

我试图了解 Haskellrecursion-schemes包中这个非常抽象的递归函数是如何工作的(或者,实际上,它是做什么的!) - 从这个文件

class Functor (Base t) => Corecursive t where

  [...]

  -- | A generalized postpromorphism
  gpostpro
    :: (Recursive t, Monad m)
    => (forall b. m (Base t b) -> Base t (m b)) -- distributive law
    -> (forall c. Base t c -> Base t c)         -- natural transformation
    -> (a -> Base t (m a))                      -- a (Base t)-m-coalgebra
    -> a                                        -- seed
    -> t
  gpostpro k e g = a . return where a = embed . fmap (ana (e . project) . a . join) . k . liftM g

特别是,我想了解的是:它如何应用g提到 monad 类型构造函数的函数m,然后返回一个t没有提到或依赖的类型的值m?我认为在 Haskell 中从任意 monad 中逃脱是不可能的!

我首先将源文件加载到 Intero 以尝试使用它的 type-at-point 功能,但该尝试失败了

然后我使用 将它加载到 GHCi 中cabal repl,并尝试通过组合函数一次一个地跟踪类型,使用 GHCi 通过注释掉定义的各个位来帮助进行类型推断。但是,当我到达 时fmap,我无法确定要注释掉的内容,因为如果我取消注释递归a调用但注释掉其他内容,我认为它甚至可能无法编译,因为部分注释掉的定义a不会有正确的类型。

4

1 回答 1

2

我设法让 ghci 通过将它们包围在(...中来告诉我子表达式的类型是什么:: _)

事实证明,诀窍是,“分配法则”k允许您将 monad 推入临时Base类型,然后该embed方法允许您放弃临时Base类型并返回t. 如果确实t没有提到具体类型IO,那么例如,就不可能k(安全地)为 IO monad 编写这样的类型。所以这里没有魔法——也就是说,没有办法使用这个函数来逃避单子,否则这些单子是无法逃避的,比如 IO。

于 2016-09-25T12:54:04.300 回答