ユーザー「singpolyma」はredditで、基礎となる一般的な構造があるかどうかを尋ねました。
data FailList a e = Done | Next a (FailList a e) | Fail e
無料のモナドが提案されましたが、これはアプリケーションファンクターを介してより一般的にモデル化できるのではないかと思いました。Abstracting with Applicativesで、Bazermanは、バイアスの方向に自然変換があれば、2つのApplicativeファンクターの合計もApplicativeファンクターであり、左右にバイアスがあることを示しています。これは私たちが必要としているもののように聞こえます!したがって、私は提案を始めましたが、すぐに問題にぶつかりました。誰かがこれらの問題の解決策を見ることができますか?:
まず、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
が問題のようです。さらに、ハッキーで⊥を使用することもオプションではありません。これは、を持っている場合に評価されるためInR (Success ...) <*> InL (Failure ...)
です。
何かが足りないような気がしますが、それが何なのかわかりません。
これはできますか?