IxpertaSolutions / freer-effects

An implementation of "Freer Monads, More Extensible Effects".
BSD 3-Clause "New" or "Revised" License
65 stars 12 forks source link

Control.Monad.forever causes <<loop>> #23

Closed schell closed 7 years ago

schell commented 7 years ago

I'm not quite sure of the root cause of this, but I can provide a minimal example of my bug. Any use of forever in an Eff r effect causes ghc to throw a <<loop>> exception. Other forms of loops (tail loops, fix) do not exhibit this bug.

{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Tests.Loop
  ( runFixLoop
  , runTailLoop
  , runForeverLoop
  ) where

import           Control.Monad       (forever)
import           Control.Monad.Freer
import           Data.Function       (fix)

-- | This loops forever as expected
fixLoop :: Member IO r => Eff r ()
fixLoop = fix $ \fxLoop -> do
  send $ putStrLn "fixLoop"
  fxLoop

runFixLoop :: IO ()
runFixLoop = runM fixLoop

-- | This loops as expected
tailLoop :: Member IO r => Eff r ()
tailLoop = send (putStrLn "tailLoop") >> tailLoop

runTailLoop :: IO ()
runTailLoop = runM tailLoop

-- | This <<loop>>s.
foreverLoop ::  Member IO r => Eff r ()
foreverLoop = forever $ send $ putStrLn "loop"

runForeverLoop :: IO ()
runForeverLoop = runM foreverLoop
schell commented 7 years ago

Furthermore, this can be seen when running freer-examples!

schell commented 7 years ago

@isovector pointed out that

the problem looks like it is due Eff's applicative instance not being lazy enough forever is defined in terms of *> replacing that with >> makes it work as expected