我尝试重新创建ST
的rank-2多态技巧,以确保某些值无法转义自定义monad。以下代码代表了我的解决方案的精神:
data STLike s a = STLike a
class Box box where
runBox :: box a -> a
run :: Box box => (forall s. box (STLike s a)) -> a
run box = let STLike a = runBox box in a
虽然上面的代码编译得很好,但是当我尝试在box (STLike s a)
上引入约束时问题就出现了:
data STLike s a = STLike a
class Box box where
runBox :: box a -> a
run :: Box box => (forall s. Eq (box (STLike s a)) => box (STLike s a)) -> a
run box = let STLike a = runBox box in a
第二个代码段无法使用以下消息进行编译:
Could not deduce (Eq (box (STLike t0 a)))
arising from a use of `box'
from the context (Box box)
bound by the type signature for
run :: Box box =>
(forall s. Eq (box (STLike s a)) => box (STLike s a)) -> a
at src/TPM/GraphDB/Event.hs:36:8-76
The type variable `t0' is ambiguous
有可能解决这个问题吗?如果不是那么为什么?
答案 0 :(得分:1)
您需要为ghc提供一种弥补该实例的方法。一种方法是:
{-# LANGUAGE FlexibleContexts, RankNTypes #-}
data STLike s a = STLike a deriving (Eq)
class Box box where
runBox :: box a -> a
newtype Boxed box a = Boxed (box a)
instance (Box box, Eq a) => Eq (Boxed box a) where
Boxed a == Boxed b = runBox a == runBox b
run :: (Eq a, Box box) => (forall s. Eq (Boxed box (STLike s a))
=> box (STLike s a))
-> a
run box = case runBox box of STLike a -> a
我认为你不能拥有instance Eq (box (STLike s a))
,所以有一点点
上面不方便的新类型。