Yuji Yamamoto (山本悠滋)
2018-12-07
QuantifiedConstraints
data Rose f x = Branch x (f (Rose f x))
instance (Eq a, forall b. Eq b => Eq (f b)) => Eq (Rose f a) where
(Branch x1 rs1) == (Branch x2 rs2) = x1 == x2 && rs1 == rs2
これはよくない!
instance (Eq a, Eq (f (Rose f a))) => Eq (Rose f a)
where
(Branch x1 c1) == (Branch x2 c2)
= x1==x1 && c1==c2
QuantifiedConstraints
を有効にすると!
instance (Eq a, forall b. Eq b => Eq (f b)) => Eq (Rose f a)
where
(Branch x1 c1) == (Branch x2 c2)
= x1 == x1 && c1 == c2
QuantifiedConstraints
を有効にすると!
contextに列挙するconstraintの中でconstraintが書けるようになる
例えば👇もOK。
従来のMonadTrans
だと、👇のMonadTrans
が定義できない!
newtype Comp t1 t2 m a = Comp { runComp :: t1 (t2 m) a }
instance (MonadTrans t1, MonadTrans t2) => MonadTrans (Comp t1 t2) where
lift = Comp . lift . lift
lift
の第1引数が守るべきMonad m
を満たせない!
• Could not deduce (Monad (t2 m)) arising from a use of ‘lift’
from the context: (MonadTrans t1, MonadTrans t2)
bound by the instance declaration at <interactive>:53:10-66
or from: Monad m
bound by the type signature for:
lift :: forall (m :: * -> *) a. Monad m => m a -> Comp t1 t2 m a
これならできる!👍
instance
(MonadTrans t1, MonadTrans t2, forall m. Monad m => Monad (t2 m))
-- (MonadTrans t1, MonadTrans t2, forall m. Monad m)
=> MonadTrans (Comp t1 t2)
where
lift = Comp . lift . lift
そもそも、👇のように書くこともできる!
class (forall m. Monad m => Monad (t m)) => MonadTrans' t where
lift :: Monad m => m a -> (t m) a
みたいに書くと、型変数m
は
の中では有効でないように読めるけど、実際には有効らしい。
forall m.
を消すとエラーになってしまうSpace, Right Arrow or swipe left to move to next slide, click help below for more details