2012-03-26 17 views
1

我想将状态monad变换器的状态参数的类型设置为该monad变换器的关联类型。但是,这导致在构建无限类型,haskell - 如何避免这种无限类型? (相关数据和StateT)

s = AssocTyp (StateT s m) a 

的直觉,为什么这是不是一个真正的问题是,

AssocTyp (StateT s m) a = AssocTyp (StateT s' m) a 

所有ss'。但是,编译器不够聪明,无法解决这个问题。我已经读过,在某些情况下,可以使用newtype来避免无限类型;我该怎么做?

这里的最小代码重现的问题,

{-# LANGUAGE KindSignatures, TypeFamilies #-} 

import Control.Monad.Trans.State 

class MyMonad (m :: * -> *) where 
    data AssocTyp m :: * -> * 

instance MyMonad m => MyMonad (StateT s m) where 
    data AssocTyp (StateT s m) a = StateTA (AssocTyp m a) 

isAssocTyp :: Monad m => (AssocTyp m a) -> m() 
isAssocTyp x = return() 

x = do 
    v <- get 
    isAssocTyp (v) 

回答

2

我不知道你想达到的目标。但是,你的状态平等,

AssocTyp (StateT s m) a = AssocTyp (StateT s' m) a 

是不正确的,因为你使用的是数据家庭,而不是一个型家庭。下面的代码编译:

{-# LANGUAGE KindSignatures, TypeFamilies #-} 

import Control.Monad.Trans.State 

class MyMonad (m :: * -> *) where 
    type AssocTyp m :: * -> * 

instance MyMonad m => MyMonad (StateT s m) where 
    type AssocTyp (StateT s m) = AssocTyp m 

isAssocTyp :: Monad m => (AssocTyp m a) -> m() 
isAssocTyp x = return() 

x :: Monad m => StateT (AssocTyp m a) m() 
x = do 
    v <- get 
    isAssocTyp v 

型家庭和数据家庭之间的区别是data families are injective,这意味着以下含义成立当DF是数据系列:

DF a b c = DF a' b' c' =====>  a = a', b = b', c = c' 

这是不是你想要什么你的情况。

+0

啊,非常感谢!我认为我在类型级别和数据级别上混淆了平等。 – gatoatigrado 2012-03-27 02:59:24

0

万一数据家人是你想要什么,我有没有类型检查的变体:

isAssocType' :: (Monad m1, Monad m0) => (AssocTyp m1 a) -> m0() 
isAssocType' _ = return() 
+0

对不起,'isAssocType'被缩小了(举例来说)。 – gatoatigrado 2012-03-27 02:58:50