haskell - Как избежать этого бесконечного типа?(Связанные данные и StateT) - PullRequest
0 голосов
/ 27 марта 2012

Я хочу установить тип параметра состояния, монадного трансформатора состояния, на связанный тип этого монадного трансформатора.Тем не менее, это приводит к созданию бесконечного типа,

s = AssocTyp (StateT s m) a

Интуиция о том, почему это на самом деле не является проблемой, заключается в том, что

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

для всех s и s'.Тем не менее, компилятор не достаточно умен, чтобы понять это.Я читал, что в некоторых случаях новый тип может использоваться, чтобы избежать бесконечных типов;как мне это сделать?

Вот свернутый код для воспроизведения вопроса,

{-# 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 ]

2 голосов
/ 27 марта 2012

Я не уверен, чего вы пытаетесь достичь. Тем не менее, равенство вы утверждаете,

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

неверно, поскольку вы используете семейство data , а не семейство type . Следующий код компилируется:

{-# 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

Разница между семействами типов и семействами данных заключается в том, что семейства данных являются инъективными , что означает следующее утверждение, если DF является семейством данных:

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

Это не то, что вы хотите в вашем случае.

0 голосов
/ 27 марта 2012

На всякий случай, если вам нужно семейство данных, у меня есть вариант проверки типа:

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