13

ユーザーsingpolyma "asked on reddit基礎となるいくつかの一般的な構造があった場合:アプリケーション・ファンクタの構成によって、短絡故障の成功リストをモデル化できますか?

data FailList a e = Done | Next a (FailList a e) | Fail e 

無料モナドが示唆されたが、これは応用的ファンクタを経由して、より一般的にモデル化することができれば、私は疑問に思いました。 Abstracting with Applicativesでは、Bazermanは、2つのアプリケーションファンクタの合計が、バイアスの方向に自然な変換を持っていれば、左右に偏りを持った応用ファンクタであることを示しています。これは私たちが必要とするように聞こえる!したがって、私は提案を始めましたが、すぐに問題に直面しました。誰でもこれらの問題の解決策を見てもらえますか?:


最初に、2つのファンクタの合計の定義から始めます。ここでは、成功型か成功型か失敗型の合計型をモデル化したいので、ここから始めました。

data Sum f g a = InL (f a) | InR (g a) 

そして、我々が仕事をしたい2ファンクタは次のとおりです。

data Success a = Success [a] 
data Failure e a = Failure e [a] 

Successはまっすぐである - それは、基本的にConst [a]です。しかし、Failure e私はそれについてはあまりよく分かりません。 pureには定義がないため、これは応用関数ではありません。しかしながら、Applyのインスタンスである:

instance Functor Success where 
    fmap f (Success a) = Success a 

instance Functor (Failure e) where 
    fmap f (Failure e a) = Failure e a 

instance Apply (Failure e) where 
    (Failure e a) <.> (Failure _ b) = Failure e a 

instance Apply Success where 
    (Success a) <.> (Success b) = Success (a <> b) 

instance Applicative Success where 
    pure = const (Success []) 
    a <*> b = a <.> b 

次に、我々は(そう左バイアス)を右から左への自然変換して、これらのファンクタの和を定義することができる:

instance (Apply f, Apply g, Applicative g, Natural g f) => Applicative (Sum f g) where 
    pure x = InR $ pure x 
    (InL f) <*> (InL x) = InL (f <*> x) 
    (InR g) <*> (InR y) = InR (g <*> y) 
    (InL f) <*> (InR x) = InL (f <.> eta x) 
    (InR g) <*> (InL x) = InL (eta g <.> x) 

そして今私たちがしなければならないのは、私たちの自然な変容を定義することだけです。そして、これはすべてが崩れ落ちるところです。

instance Natural Success (Failure e) where 
    eta (Success a) = Failure ???? a 

Failureを作成することができないことが問題になります。さらに、の場合には、と評価されるため、ハッキーで⊥を使用することもできません。

私は何かが欠けているように感じますが、それは何か分かりません。

これはできますか?

+0

nallality条件 'forall(f :: a - > b)です。 η fmap f == fmap f。 ηは、誤差成分が一定でなければならないことを強く示唆している。それで、私は 'Default e => Applicative(Failure e)'を書いています。 –

+1

また、あなたの 'Apply' /' Applicative'インスタンスは変です。ヘッドを固定してチェックするように修正しましたが、一般的にタイプチェックもしていません! 'Success a'は' Constant [a] 'と同型ではありませんが...少なくとも、より多くの型指数が必要です! –

+0

@tel - 'Default'が可能であると思われますが、私はまともな"デフォルトエラーメッセージ "が何であるか分かりません。また、あなたの編集内容は他のSO編集者によって拒否されましたが、有効です。私は自分でそれを適用します。 – ocharles

答えて

4

「正しい」答えは、eをレッドダイスの議論について嫌ったのと同じように、モノイドにすることがかなり確実です。

を検討するFailure "oops" [(*1),(*2),(*3)] <*> Failure "doh" [1,2,3]結果に「oops」または「doh」が失敗していますか?eモノイドを行うことにより、我々は何の標準的な選択肢がないという事実をキャプチャし、消費者が自分の毒を選択しましょう(もそれFirstLast[]など)

(注)このソリューションという、かなり(Maybe e, [a])表現のように、ストリーミング/潜在的に無限のデータを正しく処理することはできません。なぜなら、リストの終了に失敗したかどうかは厳密ですからです。

別のエンコードでは、フォローアップポスト(http://comonad.com/reader/2013/algebras-of-applicatives/)に従って、アプリケーションの固定点を使用します。

その後、あなたは(FixF (ProductF Embed (Sum (Const()))) a)リスト表現が提示取ると、次を得るために、ユニットの位置にあなたのエラーモノイドを貼り付けることによってそれを変える:

Monid mon => FixF (ProductF Embed (Sum (Const mon))) a

そして、あなたはMaybeを使用できることに注意してくださいを正確にに、FailListになるようにモノヨードの代わりに使用しますが、FailListの場合と同様に、エラーを組み合わせる正しい方法を指定しない限り、無料のアプリケーションインスタンスを取得しません。

はまた、我々はSuccess [(*1),(*2),(*3)] <*> Failure "doh" [1,2,3,4,5]と同等のものを持っている場合は、提案手法では、我々は3バックFailureを取得しながら、不動点アプローチで、その後私たちは三つの要素(つまり、私たちは失敗で純粋に厳格である)で逆Successを取得することに注意してください5要素不合格リストからのエラーが含まれています。これは、ストリーミングと厳格とのトレードオフです。

最後に、直接的には、type FailList e = Product (Const (First e)) ZipListを使用して標準的なアプリケーション機械を使用し、元のデータタイプに非常に近いものを得ることができます。

2
{-# LANGUAGE FlexibleInstances #-} 

instance Applicative (Sum Success (Failure e)) where 
    pure x = InL $ pure x 
    (InL f) <*> (InL x) = InL (f <*> x) 
    (InR (Failure e fs)) <*> (InR (Failure _ gs)) = InR (Failure e (fs <*> gs)) 
    (InR (Failure e fs)) <*> (InL (Success gs)) = InR (Failure e (fs <*> gs)) 
    (InL (Success gs)) <*> (InR (Failure e fs)) = InR (Failure e (gs <*> fs)) 

あなたが常に成功のリストに失敗したことを追加することができますので、これは、あなたはまた、このタイプのクラスの代わりに、Natural f g使用することができます

):

class Transplant f g where 
    transplant :: f a -> g b -> f b 

instance Transplant (Failure e) Success where 
    transplant (Failure e _) (Success a) = Failure e a 

は考えているものを、それをカテゴリ - 理論的に意味する。

+0

さて、私は 'Sum''成功'/'Failure'に対して特定の' Applicative'インスタンスを書くことができますが、これは 'Sum'の一般的なインスタンスと重複しています。また、 'Failure'と' Success 'の組み合わせについての定義は、 'Failure'がそれ以上の成功を妨げるべきであるため(左/右辺は完全に破棄されるべきです)、私が望むものではありません。 Transplateは正しい行に沿っていますが、ファンシーカテゴリ理論/抽象代数構造があるかどうかは疑問です。 – ocharles

+0

移植は、手書きのインスタンスと全く同じ方法で動作します。私は 'Failure' /' Success'の組み合わせを別のやり方でどのように定義すればいいのか分かりませんが、これは可能でしょうか? –

+0

確かに、 'Transplant'は問題ありませんが、' Sum'型のために定義しなければならないので、そこに実際の名前/カテゴリの理論的概念があるのか​​、他のアプローチがあるのか​​疑問です。 – ocharles

関連する問題