2017-02-13 75 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’ 

正確,因爲它知道必須有另一種元素在裏面。