Использование синонимов типа в монадных преобразователях - PullRequest
7 голосов
/ 30 июля 2010

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

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

-- 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?

1 Ответ

12 голосов
/ 30 июля 2010

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

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

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

Обычно преобразование невозможно без использования newtype / data, например:

type A a = Reader a Int

нельзя эквивалентно записать как type A = .... В некотором смысле эта функция будет эквивалентна лямбде \a -> Reader a Int.

уровня типа.
...