How to use Control.Monad.Cont in a recursive function?

天涯浪子 提交于 2019-12-11 05:34:43

问题


I was providing an answer to this question and an idea came to me to use Cont monad. I don't know Haskell enough to explain why this program doesn't work

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

Error -

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
   |   

But this doesn't make sense to me. Why do I have a2 and m a2? I'm expecting a and b to be of the same type.

It's bugging me because the same program works just fine in JavaScript. Maybe the Haskell one needs a type hint?

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:


return a + b parses as (return a) + b, whereas you wanted return (a + b). Remember that function application binds tighter than any infix operator.

(It's also common to write return $ a + b, which amounts to the same thing)



来源:https://stackoverflow.com/questions/54849064/how-to-use-control-monad-cont-in-a-recursive-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!