20

一対の変換関数があるとしましょう

string2int :: String -> Maybe Int
int2string :: Int -> String

Optics を使用すると、これらをかなり簡単に表すことができます。

stringIntPrism :: Prism String Int

ただし、失敗の理由を表現したい場合は、これらを 2 つの別個の関数として保持する必要があります。

string2int :: String -> Validation [ParseError] Int
int2string :: Int -> String`

この単純な例Maybeはまったく問題ありません。なぜなら、失敗は解析の失敗であると常に想定できるため、実際には、Either 型または Validation 型を使用してこれをエンコードする必要がないからです。

ただし、プリズムの解析に加えて、いくつかの検証を実行したいと考えてください。

isOver18 :: Int -> Validation [AgeError] Int
isUnder55 :: Int -> Validation [AgeError] Int

これらを一緒に構成できれば理想的です。

ageField = isUnder55 . isOver18 . string2Int :: ValidationPrism [e] String Int

これは手作業で構築するのはかなり簡単ですが、レンズ/光学の分野にはすでにこれを行う何かが潜んでいる可能性があるというのは十分に一般的な概念のようです。これを処理する既存の抽象化はありますか?

tl;dr

Maybe に直接結び付けるのではなく、任意のファンクターでパラメーター化できる部分的なレンズ/プリズム/アイソメを実装する標準的な方法はありますか?

上記の Haskell 記法はより単純なので使用しましたが、実際には Scala で Monocle を使用してこれを実装しています。ただし、ekmett の Lens ライブラリに固有の回答に完全に満足しています。

4

1 に答える 1

6

最近、インデックス付き光学系に関するブログ記事を書きました。これは、coindexed optics をどのように行うことができるかを少し調べます。

要するに: Coindexed-optics は可能ですが、それ以上の研究はまだ行われていません。特に、そのアプローチをlensレンズのエンコーディング (Profunctor から VL まで) に変換しようとすると、さらに厄介になります (ただし、型変数が 7 つだけで済むと思います)。

そして、インデックス付きオプティクスが現在 でエンコードされている方法を変更せずにこれを行うことはできませlensん。したがって、今のところは、検証固有のライブラリを使用することをお勧めします。

難しさのヒントを与えるために: Traversalsを使って作曲しようとすると、

-- like `over` but also return an errors for elements not matched
validatedOver :: CoindexedOptic' s a -> (a -> a) -> s -> (ValidationErrors, s)

または、他の何か?Coindexed Prisms しか構成できない場合、その価値はその複雑さを正当化するものではありません。それらは光学フレームワークに「適合」しません。

于 2017-04-29T20:51:36.493 に答える