代码之家  ›  专栏  ›  技术社区  ›  Mulan

如何在递归函数中使用control.monad.cont?

  •  0
  • Mulan  · 技术社区  · 7 年前

    我在回答 this question 我想到了一个主意 Cont 单子。我对哈斯克尔的了解还不足以解释为什么这个计划行不通

    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
    

    误差-

    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
       |   
    

    但这对我没有意义。为什么我有 a2 m a2 ?我期待着 a b 相同类型。

    这让我心烦,因为同一个程序在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
    1 回复  |  直到 7 年前
        1
  •  1
  •   Ben Millwood Ben    7 年前

    return a + b 解析为 (return a) + b 但是你想要 return (a + b) . 记住,函数应用程序的绑定比任何中缀运算符都要紧密。

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

    推荐文章