typeでは型引数を省略しないと高階型クラスインスタンスにできない
class Foo (a :: * -> *)
のように、高階型に実装されることを要求する型クラスに対して
data Bar a = Bar Int a
type Baz a b = Either (Bar a) b
のようにすると
class Foo (Baz a)
できなくなってしまって
type Baz a = Either (Bar a)
のようにするとできるという感じです。
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeSynonymInstances #-}
import Control.Eff (Eff, (:>))
import Control.Eff.Exception (Fail, throwExc)
import Control.Monad.Fail (MonadFail(..))
import Data.Void (Void)
import Prelude hiding (fail)
-- `a`をつけると
type Mine a = Eff (Fail :> Void) a
-- compile error !
instance MonadFail Mine where
fail _ = throwExc ()
main :: IO ()
main = return ()
Test.hs|13 col 10| error:
• The type synonym ‘Mine’ should have 1 argument, but has been given none
• In the instance declaration for ‘MonadFail Mine’
Mine
の型引数a
を消してみるとコンパイルが通る。
type Mine = Eff (Fail :> Void)
つまりモナドスタックのような構造のうち部分は、このような