2014-03-28 71 views
1

我正在嘗試編寫使用monad變換器的函數,但是關於我的monadic類型的確切結構是不可知的。儘管我不完全明白自己在做什麼 - 試圖遵循#haskell的建議。這個想法是我想寫像覆蓋條件失敗,因爲它的一個依賴關係

doSomething :: (MonadRandom m, MonadError MyError m) => Arg -> m Result 

功能(其中M爲一變壓器是添加隨機生成的狀態和錯誤處理的堆棧)

我開始寫一些狀態:

{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, FlexibleInstances #-} 

import System.Random 
import Control.Monad.Error 
import Control.Monad.State 

{- 
-- I want to make a class of monads which contain random generator state. 
class Monad m => RandMonad m where 
    putGen :: StdGen -> m() 
    getGen :: m StdGen 
-} 

-- the following creates a monadic type BT 
data BTState = BTState 
{ bGoalN :: Int 
, bRandState :: StdGen } 
newtype BT m a = BT { runBT :: StateT BTState m a } 

-- what the following does is say that if e and m can be used the 
-- way a monad error can be used, then so can e and (BT m) 
instance MonadError e m => MonadError e (BT m) where 
    throwError x = BT (throwError x) 
    -- edit: I added the following definition but I'm still getting the same error 
    -- In fact I tried every conceivable definition of catchError and still get the 
    -- same error about the coverage condition 
    catchError (BT x) y = BT (catchError y) 

當我運行此我得到「爲‘MonadError E(BT M)’非法實例聲明(覆蓋條件它的一個依賴失敗)」

我是哈斯克爾l新手,所以我不知道這是什麼意思。

+0

編輯以反映嘗試定義'catchError' – composerMike

回答

1

覆蓋條件與您如何實現實例無關。在MonadError

class (Monad m) => MonadError e m | m -> e where 

定義函數依賴性說,對於一個給定的實例m我們必須能夠唯一地確定e

的問題是,在定義像你

instance MonadError e m => MonadError e (BT m) where 

GHC不能確定要從BT m我們可以確定mm(使用實例MonadError e m),我們可以判斷e。因此,爲了定義您的實例,您需要啓用UndecidableInstances。另見How to get around the Coverage Condition for Functional Dependencies without using -XUndecidableInstances。請注意,所有MonadError實例都是這樣定義的,請參見the source

在你的情況,我建議使用現有的MonadRandom及其相應的monad變壓器RandT。你必須自己定義一個MonadError例子RandT