7

モナド変換子の型コンストラクターの引数として型同義語を使用することは可能ですか?特に、適用されたモナド変換子に単項型の同義語がある場合、それを別のモナド変換子の基になるモナドの型として使用できますか?

私が見たところ、型の同義語はファーストクラスの型コンストラクターとして受け入れられていません。以下の例とエラーメッセージを参照してください。

-- 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ますか?

4

1 に答える 1

13

タイプの同義語を部分的に適用することはできません。この特定のケースでは、あなたは書くことができます

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です。

于 2010-07-30T14:56:48.350 に答える