5

ライブラリで魔法をかけ、製品タイプを多形的に分解できるようにしたいと思います。これは、多かれ少なかれ機能するモックアップであり、私がやりたいことを示しています。

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-} 
newtype Wrapped a = Wrapped { unwrap :: a } 

-- our example structure
ex :: (Int, (Int, Int))
ex = (1,(2,3))

class WrapDecomp x y | y -> x where
    decomp :: x -> y

instance (WrapDecomp x x', WrapDecomp y y')=> WrapDecomp (x,y) (x',y') where
    decomp (x,y) = (decomp x, decomp y)

instance WrapDecomp x (Wrapped x) where
    decomp = Wrapped


example = let w = decomp ex
              (w0, w1) = decomp ex
              (w0', (w1', w2')) = decomp ex :: (Wrapped Int, (Wrapped Int, Wrapped Int))
           in print $ ( unwrap w, unwrap w0, unwrap $ snd w1, unwrap $ fst w1 )
         -- Also works:
         -- in print $ ( unwrap w, unwrap w0, unwrap w1 )

私の実際のアプリケーションはライブラリであり、上記で気付いたいぼを許容できるようにする2つのプロパティがあります。

  1. 型コンストラクターはWrappedエクスポートされません

  2. unwrapユーザーは常にバインディング内のすべてのデータを呼び出しますWrapped(私のアプリケーションの詳細が退屈なため)。したがって、実際にはあいまいさがあってはなりません。

コンセンサスUndecidableInstancesはそれほど悪くはないようですが、先に進む前に、上記がコーシャであることを確認したいと思います。


ソリューション付きの更新

私はこれに少し戸惑いましたが、TypeFamilies次のようにして問題を解決することができました:

{-# LANGUAGE TypeFamilies #-}
class Out a where
    type In a :: *
    decomp :: In a -> a

instance Out (Wrapped a) where
    type In (Wrapped a) = a
    decomp = Wrapped

instance (Out a, Out b)=> Out (a,b) where
    type In (a,b) = (In a,In b)
    decomp (x,y) = (decomp x, decomp y)
4

1 に答える 1

10

単独での使用はUndecidableInstances一般にコーシャです。これUndecidableInstancesは、タイプチェッカーが終了することを事前に証明できない場合にインスタンスを解決しようとすることを可能にします。もしそうなら、コードは、終了が事前に証明されていた場合と同じくらい安全です。

WrapDecomp x (x,y)ただし、インスタンスを使用すると、たとえば、型チェッカーが制約を引き起こす式でループする状況を作成できます。

foo x = [fst $ decomp x, x]

の使用には、いくつかのタイプとのタイプがfst必要です。したがって、whereはのタイプです。同じリストに含まれているには、テープも必要なので、decomp x(a,b)abinstance WrapDecomp t (a,b)txxa

instance WrapDecomp a (a,b)

2番目のパラメータのペアを持つ唯一のインスタンスは

instance (Wrapdecomp x x', WrapDecomp y y') => WrapDecomp (x,y) (x',y')

したがってa = (x,y)、いくつかのタイプの場合xyおよびの制約は次のようにfooなります。

WrapDecomp (x,y) ((x,y),b)

ペアインスタンスは、インスタンスがある場合、そのようなインスタンスがあると言います

WrapDecomp y b

WrapDecomp x (x,y)

これは、私たちが始めたインスタンスの正確な形式です。

于 2012-08-04T20:20:28.347 に答える