0

Поэтому у меня есть этот кодтипа ограничения для полиморфных функций, как лифт

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

import MonadA 

data A = A 

newtype MonadA a => MyStateT a b { runMyStateT :: StateT A a b } 
    deriving (Functor, Applicative, Monad, MonadIO, MonadState A) 

instance MonadTrans MyStateT where 
    lift = MyStateT . lift 

и я получаю компилятор жалуется, что не может доказать m от подписи lift имеет типа MonadA или вот как я прочитал эти загадочные ошибки Сообщения.

Could not deduce (MonadA m) arising from a use of `MyStateT' 
from the context (Monad m) 
    bound by the type signature for 
      lift :: Monad m => m a -> MyStateT m a 

есть ли способ справиться с этим? Я думаю, что нужно ограничение, чтобы иметь возможность создать экземпляр следующим образом:

instance MonadA a => MonadA (MyStateT a) where 
    f = MyStateT . lift . f 

Также будет такая реализация f работы? (Я не получил этого далеко из-за вышеупомянутой ошибки). Я надеюсь, что f с правой стороны разрешить f над внутренней монадой a.


Edit: Это действительно помогло понизить ограничение типа в newtype MonadA a => MyStateT ..., чтобы избежать точной ошибки, которые я упомянул. Однако там было просто другая ошибка, которую я ранее приписан к тому же, считаю это продолжение примера коды выше (некоторые части повторяются, теперь без ограничений типа):

class MonadB m where 
    fB :: m() 

newtype MyStateT m a = MyStateT { runMyStateT :: StateT A m a} 
    deriving (... MonadState A ...) 

instance MonadTrans MyStateT where 
    lift = MyStateT . lift 

instance MonadA a => MonadA (MyStateT a) where 
    f = lift . f 

instance MonadA a => MonadB (MyStateT a) where 
    fB = lift (modify (...)) 

ошибка является

Could not deduce (a ~ StateT A m0) from context (MonadA (MyStateT a), MonadA a) 

в реализации fB. Раньше я пробовал class MonadA m => MonadB m безрезультатно. Не имеет смысла также сопоставлять a с StateT A m. Поскольку MyStateT является экземпляром MonadState A, он должен работать, нет?

Edit:

ОК, получил это работает:

fB = MyStateT (modify ...) 

глупо меня.

ответ

4

Решение снижается ограничение от MyStateT определения:

newtype MyStateT a b { runMyStateT :: StateT A a b } 
    deriving (Functor, Applicative, Monad, MonadIO, MonadState A) 

ограничения типов данных, по существу, бесполезны, так как вам нужно поместить их в подписи функции в любом случае. По этой причине эта функция фактически равна deprecated.

Я думаю, что нужно ограничение, чтобы иметь возможность создать экземпляр следующим образом:

не очень; instance MonadA a => MonadA (MyStateT a) будет работать отлично.

Будет ли такая реализация f работать?

Будет.Обратите внимание, что, как вы предоставили MonadTrans экземпляр для MyStateT, вы на самом деле не нужно обернуть MyStateT явно:

instance MonadA a => MonadA (MyStateT a) where 
    f = lift . f