代码之家  ›  专栏  ›  技术社区  ›  Nikita Volkov

秩-2多态性及其约束

  •  2
  • Nikita Volkov  · 技术社区  · 12 年前

    我正试图重现 ST s 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 回复  |  直到 12 年前
        1
  •  1
  •   aavogt    12 年前

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

    推荐文章