Rank-2多态性和约束

时间:2013-09-22 00:46:10

标签: haskell polymorphism higher-rank-types

我尝试重新创建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

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

1 个答案:

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