2017-07-20 18 views
0

Linear.V型のnewtypeラッパーを作成し、有用なインスタンスを導出しようとしています。私はこれをしようとしていた。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) 

をコンパイラがあることを把握することができないように私には思われますとBar nの両方のIndexIntです。しかし、私はそれについては分かりません。

答えて

1

あなたはほとんどそこにいます。残りの問題は、最終的に関数Bar n -> f (Bar n)を返さなければならないラッパータイプBar nixトラバーサルに最終的に関数V n Foo -> f (V n Foo)を返す、基礎となるV n Fooixtraversalを変換しています。これを知るには、Traversal'の定義を "解凍"する必要があります。あなたのコードで

ix i f vf (V n Foo)型を持つので、 Barコンストラクタで fmapに十分である:

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) 
+0

おかげで、これは私にとって受け入れ可能な解決策です。ランタイムオーバーヘッドがゼロになると思いますよね?何らかの理由で 'deriving'メカニズムを使ってこれを行うことができますか? – user1747134

+0

@ user1747134これは新しいタイプなので、オーバーヘッドはありません。私はそこに「派生」を使う方法はないと思う。 – danidiaz

関連する問題