代码之家  ›  专栏  ›  技术社区  ›  user1747134

导出线性包装时的一个类型检查错误

  •  0
  • user1747134  · 技术社区  · 9 年前

    我正在尝试为 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 机制,因为它似乎更易于重用。

    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)
    

    Index V n Foo Bar n Int .但我对此不确定。

    1 回复  |  直到 9 年前
        1
  •  1
  •   danidiaz    9 年前

    你就快到了。剩下的问题是转换 ix traversal V n Foo ,最终返回一个函数 V n Foo -> f (V n Foo) 九、 包装器类型的遍历 Bar n Bar n -> f (Bar n) .我们必须“解开”定义 Traversal'

    ix i f v 具有类型 f (V n Foo) ,所以这就足够了 fmap Bar

    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)
    
    推荐文章