2016-07-06 4 views
4

私は、値(多態性、何でもよい)を持つコントロールフローのデータに取り組んでいます。また、に値がまだ良いかどうかを確認するバリデータ関数を持っていて、に関数それは "値をリフレッシュする"(新しい値で新しいデータを返します)。タイプレベルでオプションのフィールドを使用してデータを表現するにはどうすればよいですか?

バニラHaskellでは、それは次のようになります。

data Refreshable = Refreshable | NotRefreshable 
data Validatable = Validatable | NotValidatable 
MyData (r :: Refreshable) (v :: Validatable) 

私はちょうどそれだけRefreshableでやった:私は実際に欲しい

data MyData a = MyData 
    {value :: a 
    ,validator :: Maybe (a -> Bool) 
    ,refresher :: Maybe (MyData a -> MyData a)} 

は、これらのタイプがあります。 Validatableでもやってみたいですが、コンストラクタに問題があります。ちょうどRefreshableのために私は2つのコンストラクタを必要とします.1つは更新可能なデータ用で、もう1つは更新不可能なデータ用です。 validatableで、私は4コンストラクタを持つ必要があります! (リフレッシュ可能で有効性があり、リフレッシュ不可能で有効性があり、有効性があり、リフレッシュ不可能であり、リフレッシュ不可能であり、有効性がない)。後で別のオプションのフィールドが必要になったら想像してください。さらに悪いことに、変更されているフィールドを除いてほとんどすべてのフィールドが同じです。重複が多くあります。


私はまた、型式/タイプファミリで状況を修正しようとしました。
たとえば、MyData 'Refreshable 'NotValidatableRefreshable data => dataになります。MyDataをインスタンス化することもできますし、より具体的なデータとしてインスタンス化することもできます。

実際にはフィールドではないので、これも問題です。つまり、バリデータなしでデータを取得して、バリデーター(タイプレベルではない)と同じデータに変更することはできません。


おそらくXYの問題です。私は、より洗練されたアプローチは、Refreshable aValidatable aのようなデータ型を作成し、それらをMyDataで構成することですが、私はそれを行う方法を知らないと思う。順序がすべてを変えるので、私はそれらをラップすることはできません。

これを行うにはきれいな方法がありますか?または私はちょうど4コンストラクタに固執する必要がありますか?またはおそらくハスケルはこのタイプのものの準備が整っていないでしょうか? (意図された馬小屋はありません:P)。

答えて

6

あなたの要件を満たすものはありますか?

import Control.Applicative (Const) 
import Data.Functor.Identity 

data MyData kv kr a = MyData 
    {value :: a 
    ,validator :: kv (a -> Bool) 
    ,refresher :: kr (MyData a -> MyData a)} 

-- examples 
type FullData a  = Data Identity Identity a 
type EmptyData a  = Data (Const()) (Const()) a 
type ValidableData a = Data Identity (Const()) a 

いくつかのラッピング/アンラッピングが必要です(Identity)。

ニーモニック別名type Present = Identitytype Missing = Const()をいくつかの拡張子を付けて定義できます。また


data MyData (v :: Opt) (r :: Opt) a = MyData 
    {value :: a 
    ,validator :: Validator v a 
    ,refresher :: Refresher r a} 

data Opt = Yes | No 

type family Validator (o :: Opt) a where 
    Validator Yes = (a -> Bool) 
    Validator No =() 
-- etc. 

-- examples 
type FullData a  = Data Yes Yes a 
type EmptyData a  = Data No No a 
type ValidableData a = Data Yes No a 
+0

ああ賢いです!私はそれがうまくいくと思います、今しようとします。 – MasterMastic

2

私はカイの答えからの変化量になってしまった:

data Opt = Yes | No 

type family TOpt (o :: Opt) a where 
    TOpt Yes a = a 
    TOpt No a =() 

そして、このような何か:

data MyData (v :: Opt) a = MyData 
    {val :: a 
    ,validator :: TOpt v (MyData 'Yes a -> Bool) 
    ... 
    } 
関連する問題