在monad变换器中使用类型同义词

时间:2010-07-30 14:19:02

标签: haskell types monad-transformers

是否可以使用类型同义词作为monad变换器类型构造函数的参数?特别是,如果应用的monad变换器有一元类型的同义词,它是否可以用作另一个monad变换器中底层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

1 个答案:

答案 0 :(得分:12)

无法部分应用类型同义词。在这种特定情况下,您可以编写

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

[甚至更好type B = ReaderT String A在另一个monad变换器中使用B]

一般情况下,如果不使用newtype / data,转换是不可能的,例如:

type A a = Reader a Int

不能等效地写为type A = ...。在某种意义上,此功能将等同于类型级lambda \a -> Reader a Int