Applicative
型クラスは、型指定された機能のカテゴリにデカルトmonoidal構造を保持ずさんmonoidalファンクタを表します。
言い換えると(,)
、モノイド構造を形成する正準同型が見られる場合:
-- Implementations left to the motivated reader
assoc_fwd :: ((a, b), c) -> (a, (b, c))
assoc_bwd :: (a, (b, c)) -> ((a, b), c)
lunit_fwd :: ((), a) -> a
lunit_bwd :: a -> ((), a)
runit_fwd :: (a, ()) -> a
runit_bwd :: a -> (a, ())
タイプクラスとその法則は、次のように書くこともできます。
class Functor f => Applicative f
where
zip :: (f a, f b) -> f (a, b)
husk :: () -> f ()
-- Laws:
-- assoc_fwd >>> bimap id zip >>> zip
-- =
-- bimap zip id >>> zip >>> fmap assoc_fwd
-- lunit_fwd
-- =
-- bimap husk id >>> zip >>> fmap lunit_fwd
-- runit_fwd
-- =
-- bimap id husk >>> zip >>> fmap runit_fwd
同じ構造に関してoplaxモノイドであるファンクタがどのように見えるか疑問に思うかもしれません。
class Functor f => OpApplicative f
where
unzip :: f (a, b) -> (f a, f b)
unhusk :: f () -> ()
-- Laws:
-- assoc_bwd <<< bimap id unzip <<< unzip
-- =
-- bimap unzip id <<< unzip <<< fmap assoc_bwd
-- lunit_bwd
-- =
-- bimap unhusk id <<< unzip <<< fmap lunit_bwd
-- runit_bwd
-- =
-- bimap id unhusk <<< unzip <<< fmap runit_bwd
定義や法律に含まれる種類について考えると、残念な真実が明らかになります。OpApplicative
制約は具体的なものではありませんFunctor
。
instance Functor f => OpApplicative f
where
unzip fab = (fst <$> fab, snd <$> fab)
unhusk = const ()
ただし、すべてのApplicative
ファンクター(実際にはFunctor
)は取るに足らないものではありますOpApplicative
が、Applicative
弛緩とOpApplicative
弛緩の間には必ずしも良い関係があるとは限りません。したがって、デカルトのモノイド構造に対して強力なモノイド関数を探すことができます。
class (Applicative f, OpApplicative f) => StrongApplicative f
-- Laws:
-- unhusk . husk = id
-- husk . unhusk = id
-- zip . unzip = id
-- unzip . zip = id
このタイプの唯一の住人() -> ()
はの恒等関数なので、上記の最初の法則は簡単()
です。
ただし、残りの3つの法則、つまりサブクラス自体は簡単ではありません。特に、すべてApplicative
がこのクラスの合法的なインスタンスであるとは限りません。
以下は、Applicative
合法的なインスタンスを宣言できるファンクターですStrongApplicative
。
Identity
VoidF
(->) r
(回答を参照)Monoid m => (,) m
Vec (n :: Nat)
Stream
(無限)
そしてここにApplicative
私たちができないいくつかのsがあります:
[]
Either e
Maybe
NonEmptyList
ここでのパターンは、ことを示唆しているStrongApplicative
クラスが意味であるFixedSize
クラス、「固定サイズ」*多重度という意味**の住民a
の住民でf a
固定されています。
これは、2つの推測として述べることができます。
Applicative
タイプ引数の要素の「固定サイズ」コンテナを表すものはすべて、StrongApplicative
StrongApplicative
の発生数a
が変化する可能性のあるのインスタンスは存在しません
誰もがこれらの推測を否定する反例、またはそれらが真または偽である理由を実証するいくつかの説得力のある推論について考えることができますか?
*形容詞の「固定サイズ」を適切に定義していないことに気づきました。残念ながら、このタスクは少し循環的です。「固定サイズ」のコンテナの正式な説明は知りませんが、それを考え出そうとしています。StrongApplicative
これまでの私の最善の試みです。
ただし、これが適切な定義であるかどうかを評価するには、比較する必要があります。ファンクターがその型引数の住人に関して特定のサイズまたは多重度を持つことの意味のいくつかの正式/非公式の定義を考えると、問題は、StrongApplicative
インスタンスの存在が固定サイズと変動サイズのファンクターを正確に区別するかどうかです。
既存の正式な定義を意識せずに、「固定サイズ」という言葉の使い方を直感に訴えています。しかし、誰かがファンクタのサイズに関する既存の形式主義をすでに知っStrongApplicative
ており、それと比較できる場合は、はるかに優れています。
**「多重度」とは、ファンクターのコドメインタイプの生息地でファンクターのパラメータータイプの任意の要素が「いくつ」発生するかを大まかに意味します。これはせずファンクタが適用される特定のタイプに関して、ひいてはパラメータ・タイプのいずれかの特定の住民に関係なく。
これについて正確ではないため、コメントに混乱が生じたため、さまざまなファンクタのサイズ/多重度を次のように検討する例をいくつか示します。
VoidF
:固定、0Identity
:固定、1Maybe
:変数、最小0、最大1[]
:変数、最小0、最大無限NonEmptyList
:変数、最小1、最大無限Stream
:固定、無限Monoid m => (,) m
:固定、1data Pair a = Pair a a
:固定、2Either x
:変数、最小0、最大1data Strange a = L a | R a
:固定、1
(->) r
です。
(->) r
。強力な適用構造を維持するには、同型のコンポーネントが必要です。何らかの理由でRepresentable
Haskellでは型クラスは、神秘的な持っているtabulate . return = return
(実際にも、非モナドファンクタのために意味がありません)法律を、それは私たちがそれを言う必要条件の1/4与えtabulate
とzip
モノイドの、適切なカテゴリの射ですが。他の3つは、あなたが要求しなければならない追加の法律です。
tabulate
とindex
...、適切なカテゴリの射ている」
return
は深刻な問題ではないことが判明しました。cotraverse getConst . Const
デフォルトの実装であるreturn
/ pure
の面でDistributive
distributives / representablesは実装が一意であることを、形状を固定しているため、と。