如何在递归函数中使用Control.Monad.Cont?

Tha*_*you 1 monads continuations haskell type-mismatch do-notation

我正在提供这个问题的答案,我想到了使用Contmonad 的想法.我不知道Haskell足以解释为什么这个程序不起作用

import Control.Monad.Cont

fib1 n = runCont (slow n) id
  where
    slow 0 = return 0
    slow 1 = return 1
    slow n = do
      a <- slow (n - 1)
      b <- slow (n - 2)
      return a + b

main = do
  putStrLn $ show $ fib1 10
Run Code Online (Sandbox Code Playgroud)

错误 -

main.hs:10:18: error:
    • Occurs check: cannot construct the infinite type: a2 ~ m a2
    • In the second argument of ‘(+)’, namely ‘b’
      In a stmt of a 'do' block: return a + b
      In the expression:
        do a <- slow (n - 1)
           b <- slow (n - 2)
           return a + b
    • Relevant bindings include
        b :: a2 (bound at main.hs:9:7)
        a :: a2 (bound at main.hs:8:7)
        slow :: a1 -> m a2 (bound at main.hs:5:5)
   |
10 |       return a + b
   |   
Run Code Online (Sandbox Code Playgroud)

但这对我来说没有意义.我为什么要a2m a2?我期待ab成为同一类型.

这让我烦恼,因为同样的程序在JavaScript中运行得很好.也许Haskell需要一个类型提示?

const runCont = m => k =>
  m (k)

const _return = x =>
  k => k (x)
  
const slow = n =>
  n < 2
    ? _return (n)
    : slow (n - 1) (a =>
      slow (n - 2) (b =>
      _return (a + b)))
      
const fib = n =>
  runCont (slow(n)) (console.log)
  
fib (10) // 55
Run Code Online (Sandbox Code Playgroud)

Ben*_*ood 5

return a + b解析为(return a) + b,而你想要return (a + b).请记住,函数应用程序比任何中缀运算符都更紧密.

(编写也很常见return $ a + b,这相当于同样的事情)