Linear.V派生封装器中的类型检查错误

我正在尝试为Linear.V类型创建一个新类型的包装并派生有用的实例。 我正在尝试这个:

{-# LANGUAGE DataKinds, PolyKinds, ScopedTypeVariables, 
StandaloneDeriving, FlexibleContexts, UndecidableInstances, 
GeneralizedNewtypeDeriving, PartialTypeSignatures, TypeFamilies #-}

import Linear.V 
import Control.Lens.At

data Foo = Foo1 | Foo2 deriving (Show, Eq)

尝试1 - 我会认为GeneralizedNewtypeDeriving会做,但不会:

newtype Bar n = Bar {
  getBar :: V n Foo
} deriving (Show, Eq, Ixed)

我得到这个错误:

    • Couldn't match representation of type ‘f (V n Foo)’
                               with that of ‘f (Bar n)’
        arising from the coercion of the method ‘ix’
          from type ‘Index (V n Foo)
                     -> Control.Lens.Type.Traversal' (V n Foo) (IxValue (V n Foo))’
            to type ‘Index (Bar n)
                     -> Control.Lens.Type.Traversal' (Bar n) (IxValue (Bar n))’
      NB: We cannot know what roles the parameters to ‘f’ have;
        we must assume that the role is nominal
    • When deriving the instance for (Ixed (Bar n))

我已经使用独立派生尝试2,如下所示:

newtype Bar n = Bar {
  getBar :: V n Foo
} deriving (Show, Eq)
type instance Index (Bar n) = Int
type instance IxValue (Bar n) = Foo

deriving instance Ixed (V n Foo) => Ixed (Bar n)

但后来我得到了一个不同的错误:

• Couldn't match representation of type ‘f1 (V n Foo)’
                           with that of ‘f1 (Bar n)’
    arising from a use of ‘GHC.Prim.coerce’
  NB: We cannot know what roles the parameters to ‘f1’ have;
    we must assume that the role is nominal
• In the expression:
    GHC.Prim.coerce
      @(Index (V n Foo)
        -> Control.Lens.Type.Traversal' (V n Foo) (IxValue (V n Foo)))
      @(Index (Bar n)
        -> Control.Lens.Type.Traversal' (Bar n) (IxValue (Bar n)))
      ix
  In an equation for ‘ix’:
      ix
        = GHC.Prim.coerce
            @(Index (V n Foo)
              -> Control.Lens.Type.Traversal' (V n Foo) (IxValue (V n Foo)))
            @(Index (Bar n)
              -> Control.Lens.Type.Traversal' (Bar n) (IxValue (Bar n)))
            ix
  When typechecking the code for ‘ix’
    in a derived instance for ‘Ixed (Bar n)’:
    To see the code I am typechecking, use -ddump-deriv
  In the instance declaration for ‘Ixed (Bar n)’
• Relevant bindings include
    ix :: Index (Bar n)
          -> Control.Lens.Type.Traversal' (Bar n) (IxValue (Bar n))
      (bound at a.hs:12:1)

我不确定为什么其中任何一个错误实际发生。 这可以以某种方式完成吗? 我对高级类型功能并不是很熟悉,至今我也无法手动编写这个特定的实例定义,所以我会考虑这个解决方案。 但我宁愿使用deriving机制,因为它似乎更可重用。

编辑:我试过这个手动实例decalaration:

type instance Index (Bar n) = Int
type instance IxValue (Bar n) = Foo

instance Ixed (Bar n) where
  ix i f (Bar v) = ix i f v

但是,产生以下错误:

• Couldn't match type ‘V n Foo’ with ‘Bar n’
  Expected type: f (Bar n)
    Actual type: f (V n Foo)
• In the expression: ix i f v
  In an equation for ‘ix’: ix i f (Bar v) = ix i f v
  In the instance declaration for ‘Ixed (Bar n)’
• Relevant bindings include
    v :: V n Foo (bound at a.hs:14:15)
    f :: IxValue (Bar n) -> f (IxValue (Bar n)) (bound at a.hs:14:8)
    i :: Index (Bar n) (bound at a.hs:14:6)
    ix :: Index (Bar n)
          -> Control.Lens.Type.Traversal' (Bar n) (IxValue (Bar n))
      (bound at a.hs:14:3)

在我看来,编译器无法弄清楚V n FooBar nIndex是否是Int 。 但我不确定这一点。


你几乎在那里。 剩下的问题是转换底层V n Fooix遍历,它最终返回一个函数V n Foo -> f (V n Foo)到包装类型Bar nix遍历,最终返回一个函数Bar n -> f (Bar n) 。 我们必须“解开” Traversal'的定义来了解这一点。

在你的代码中, ix ifv类型为f (V n Foo) ,所以fmapBar构造函数足够了:

type instance Index (Bar n) = Int
type instance IxValue (Bar n) = Foo

instance Ixed (Bar n) where
  ix i f (Bar v) = fmap Bar (ix i f v)
链接地址: http://www.djcxy.com/p/43461.html

上一篇: A typecheck errors in deriving wrapper for Linear.V

下一篇: Can I implement this newtype as a composition of other types?