2014-03-28 158 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