2017-02-13 52 views
2

我试图运行此代码自由:奇怪`freer`类型的错误

{-# LANGUAGE DataKinds  #-} 
{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE GADTs   #-} 
{-# LANGUAGE TupleSections #-} 
{-# LANGUAGE TypeOperators #-} 

module Lib where 

import   Control.Monad.Freer 
import   Control.Monad.Freer.Internal 
import   Control.Monad.Freer.State 
import   Data.IORef 

runStateIO :: (Member (State s) r, Member IO r) => IORef s -> Eff (State s ': r) a -> Eff r (a,s) 
runStateIO ref = loop 
    where 
    loop (Val v) = (v,) <$> send (readIORef ref) 
    loop (E u q) = 
     case decomp u of 
     Right Get  -> send (readIORef ref) >>= loop . qApp q 
     Right (Put s) -> send (writeIORef ref s) >> loop (qApp q()) 
     Left u'  -> E u' (tsingleton (loop . qApp q)) 

statefulFac :: Member (State Int) r => Int -> Eff r() 
statefulFac 1 = return() 
statefulFac n = do 
    a <- get 
    put (n * a) 
    statefulFac (n - 1) 

runStatefulFac_IO :: Int -> IO Int 
runStatefulFac_IO n = do 
    ref <- newIORef 1 :: IO (IORef Int) 

    let 
     -- none of these work: 
     -- stateful_fac :: (Member (State Int) r, Member IO r) => Eff r() 
     -- stateful_fac :: Eff '[IO, State Int]() 
     -- stateful_fac :: Eff '[State Int, IO]() 
     stateful_fac = statefulFac 5 

     r = runStateIO ref stateful_fac 

    -- runM r 
    undefined 

runStatefulFac_pure :: Int -> Int 
runStatefulFac_pure n = snd (run (runState (statefulFac n) 1)) 

这是用股票freer,除了我出口的State影响施工人员能够运行runStateIO口译员。问题是它的失败与

example.hs:42:11: error: 
    • Ambiguous type variable ‘r0’ arising from a use of ‘runStateIO’ 
     prevents the constraint ‘(Data.Open.Union.Internal.Member' 
            (State Int) 
            r0 
            (Data.Open.Union.Internal.FindElem 
            (State Int) r0))’ from being solved. 
     Relevant bindings include 
     r :: Eff r0 ((), Int) (bound at example.hs:42:7) 
     stateful_fac :: Eff (State Int : r0)() (bound at example.hs:40:7) 
     Probable fix: use a type annotation to specify what ‘r0’ should be. 
     These potential instances exist: 
     two instances involving out-of-scope types 
      instance [safe] (r ~ (t' : r' : rs'), 
          Data.Open.Union.Internal.Member' t (r' : rs') n) => 
          Data.Open.Union.Internal.Member' 
          t r ('Data.Open.Union.Internal.S n) 
      -- Defined in ‘Data.Open.Union.Internal’ 
      instance [safe] r ~ (t : r') => 
          Data.Open.Union.Internal.Member' t r 'Data.Open.Union.Internal.Z 
      -- Defined in ‘Data.Open.Union.Internal’ 
    • In the expression: runStateIO ref stateful_fac 
     In an equation for ‘r’: r = runStateIO ref stateful_fac 
     In the expression: 
     do { ref <- newIORef 1 :: IO (IORef Int); 
      let stateful_fac = statefulFac 5 
       r = runStateIO ref stateful_fac; 
      undefined } 

我想知道(1)这是什么消息想说(2)有什么错此代码,如何解决呢?谢谢。

回答

3

我认为这是在此签名

runStateIO :: (Member (State s) r, Member IO r) => IORef s -> Eff (State s ': r) a -> Eff r (a,s) 

你不应该在约束Member (State s) r,因为你是直接谈论State s ': r。所以,如果你写

runStateIO :: (Member IO r) => IORef s -> Eff (State s ': r) a -> Eff r (a,s) 

那么你在main要签名应该工作

let stateful_fac = statefulFac 5 :: Eff '[State Int, IO]() 

编译器仍然希望找到一种方式为State Int为R的一员后,State Int已经被“解读”。所以,如果我使用的签名上面stateful_fac编译器会抱怨:

• Couldn't match type ‘'[]’ with ‘r'0 : rs'0’ 
    arising from a use of ‘runStateIO’ 

正确,因为它知道必须有另一种元素在里面。