2010-07-30 2 views
7

Можно ли использовать синонимы типа в качестве аргументов конструктора типа monad-трансформаторов? В частности, если существует синоним унитарного типа для примененного монадного трансформатора, можно ли его использовать как тип базовой монады в другом монадном трансформаторе?Использование синонимов типа в монадных трансформаторах

Из того, что я вижу синонимы типа не принимаются в качестве конструкторов типа первого класса, см примера и сообщения об ошибках ниже:

-- Using type synonym of a monad transformer in another monad transformer. 

import Control.Monad.Reader 

-- inner transformer 
type A a = ReaderT Int IO a 

-- type B a = ReaderT String A a 
{- Error: 
readert2.hs:8:0: 
    Type synonym `A' should have 1 argument, but has been given 0 
    In the type synonym declaration for `B' 
-} 

-- type B a = ReaderT String (A a) a 
{- Error: 
readert2.hs:15:27: 
    Kind mis-match 
    The second argument of `ReaderT' should have kind `* -> *', 
    but `A a' has kind `*' 
    In the type `ReaderT String (A a) a' 
    In the type synonym declaration for `B' 
-} 

type B a = ReaderT String (ReaderT Int IO) a 
{- OK -} 

main = do 
    r <- flip runReaderT 39 $ do 
      n <- ask :: A Int 
      s <- flip runReaderT "foo" $ (ask :: B String) 
      return $ n + length s 
    print r 

Есть ли способ, чтобы избежать расширений синонима типа A в определении B a ?

ответ

12

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

type A = ReaderT Int IO 
type B a = ReaderT String A a 

[или даже лучше type B = ReaderT String A использовать B в другой монады трансформатор]

Это вообще, что трансформация невозможна без использования NewType/данных, например:

type A a = Reader a Int 

не может быть эквивалентно обозначен как type A = .... В некотором смысле эта функция будет эквивалентна лямбда уровня.

Смежные вопросы