2

我正在尝试重新创建STs rank-2 多态性技巧,以确保某些值无法逃脱自定义单子。以下代码代表了我的解决方案的精神:

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

有可能解决这个问题吗?如果不是那为什么?

4

1 回答 1

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)),所以上面有一个稍微不方便的新类型。

于 2013-09-22T06:12:42.507 回答