32

Typeclassopedia(他のソースの中でも)によると、Applicative論理的には型クラス階層のMonadPointed(したがってFunctor)に属しているので、Haskellの前奏曲が今日書かれた場合、理想的には次のようなものになります。

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Functor f => Pointed f where
    pure :: a -> f a

class Pointed f => Applicative f where
    (<*>) :: f (a -> b) -> f a -> f b

class Applicative m => Monad m where
    -- either the traditional bind operation
    (>>=) :: (m a) -> (a -> m b) -> m b
    -- or the join operation, which together with fmap is enough
    join :: m (m a) -> m a
    -- or both with mutual default definitions
    f >>= x = join ((fmap f) x)
    join x = x >>= id
    -- with return replaced by the inherited pure
    -- ignoring fail for the purposes of discussion

(これらのデフォルトの定義がウィキペディアの説明から私によって再入力された場合、エラーは私自身のものですが、エラーがある場合は少なくとも原則として可能です。)

ライブラリは現在定義されているため、次のようになります。

liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM ::       (Monad m) => (a -> b) -> m a -> m b

と:

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap    ::       (Monad m) => m (a -> b) -> m a -> m b

各ペア内のこれらのタイプ間の類似性に注意してください。

私の質問は次のとおりです。liftM(とは異なるliftA)とap(とは異なる)は、単に、念頭に置いて設計されていない<*>歴史的現実の結果ですか?それとも、コンテキストのみを必要とするバージョンとは異なる、他の動作方法(場合によっては、いくつかの法的な定義)ですか?MonadPointedApplicativeMonadApplicative

それらが異なる場合、(Typeclassopediaや他の場所で説明されているが、型システムによって強制されていない、、、、および定義に必要なMonad法則に従う)定義の単純なセットを提供できますか?ApplicativePointedFunctorliftAliftM

あるいは、それらが明確でない場合、前提と同じ法則を使用してそれらの同等性を証明できますか?

4

2 に答える 2

26

liftA、、、、およびすべて同じ関数であるliftM必要があり、ファンクターの法則を満たしている場合は次のようになります。fmap.

fmap id = id

ただし、これはHaskellによってチェックされていません。

今、適用のために。タイプと法則を満たす実装が複数存在する可能性があるという理由だけで、一部のファンクターが区別できる可能性がapあります。<*>たとえば、Listには複数の可能なApplicativeインスタンスがあります。次のようにアプリケーションを宣言できます。

instance Applicative [] where
  (f:fs) <*> (x:xs) = f x : fs <*> xs
  _      <*> _      = []
  pure              = repeat

ap関数は引き続きとして定義されます。liftM2 idこれは、Applicativeすべてのに無料で提供されるインスタンスですMonad。しかし、ここに複数のインスタンスを持つ型コンストラクターの例がありApplicative、どちらも法則を満たしています。ただし、モナドと適用可能なファンクターが一致しない場合は、それらに異なるタイプを設定することをお勧めします。たとえば、Applicative上記のインスタンスはのモナドと一致しないため[]、実際に言ってから、の代わりにnewtype ZipList a = ZipList [a]の新しいインスタンスを作成する必要があります。ZipList[]

于 2009-10-28T04:31:06.487 に答える
9

それら異なる可能性がありますが、異なるべきではありません

実装が異なる可能性があるため、異なる可能性があります。一方はで定義されinstance Applicative、もう一方はで定義されますinstance Monad。しかし、それらが実際に異なる場合は、それらのインスタンスを作成したプログラマーが誤解を招くコードを作成したと言えます。

あなたは正しいです:機能は歴史的な理由で存在するのと同じように存在します。人々は物事がどうあるべきかについて強い考えを持っています。

于 2009-10-28T08:01:16.780 に答える