223

型クラス X とは何かを誰かに説明しているときに、正確に X であるデータ構造の良い例を見つけるのに苦労しています。

そこで、次の例をリクエストします。

  • Functor ではない型コンストラクター。
  • Functor であるが Applicative ではない型コンストラクター。
  • Applicative であるが Monad ではない型コンストラクター。
  • モナドである型コンストラクタ。

Monad の例はいたるところにたくさんあると思いますが、Monad の良い例と前の例との関係があれば、全体像を完成させることができます。

特定の型クラスに属するために重要な側面のみが異なり、互いに類似している例を探します。

この階層のどこかに Arrow の例を忍び込ませることができれば (それは Applicative と Monad の間にありますか?)、それも素晴らしいことです!

4

5 に答える 5

104

Functor ではない型コンストラクタ:

newtype T a = T (a -> Int)

それから反変ファンクターを作成できますが、(共変) ファンクターは作成できません。書いてみてくださいfmap、失敗します。反変ファンクターのバージョンが逆になっていることに注意してください。

fmap      :: Functor f       => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a

ファンクタであるがApplicativeではない型コンストラクタ:

いい例がありません。ありますがConst、理想的には具体的な非モノイドが欲しいのですが、何も思いつきません。すべての型は基本的に、数値、列挙、積、合計、または関数です。以下の pigworker を見ることができData.VoidますMonoid

instance Monoid Data.Void where
    mempty = undefined
    mappend _ _ = undefined
    mconcat _ = undefined

_|_は Haskell の正当な値であり、実際には の唯一の正当な値であるためData.Void、これはモノイド規則を満たしています。unsafeCoerce関数を使用するとすぐに、プログラムがHaskellセマンティクスに違反しないことが保証されなくなったため、それと何の関係があるのか​​ わかりませんunsafe

下部 (リンク) または安全でない関数 (リンク)に関する記事については、Haskell Wiki を参照してください。

さまざまな拡張機能を備えた Agda や Haskell など、より豊富な型システムを使用して、そのような型コンストラクターを作成できるかどうか疑問に思っています。

Applicative であるが Monad ではない型コンストラクタ:

newtype T a = T {multidimensional array of a}

次のようなものを使用して、それから Applicative を作成できます。

mkarray [(+10), (+100), id] <*> mkarray [1, 2]
  == mkarray [[11, 101, 1], [12, 102, 2]]

しかし、モナドにすると、次元の不一致が発生する可能性があります。このような例は、実際にはまれであると思います。

モナドである型コンストラクタ:

[]

矢印について:

矢印がこの階層のどこにあるかを尋ねることは、「赤」がどのような形であるかを尋ねるようなものです。種類の不一致に注意してください。

Functor :: * -> *
Applicative :: * -> *
Monad :: * -> *

しかし、

Arrow :: * -> * -> *
于 2011-08-28T11:04:52.857 に答える
91

私のスタイルは私の電話で窮屈かもしれませんが、ここに行きます.

newtype Not x = Kill {kill :: x -> Void}

Functor にすることはできません。もしそうなら、私たちは持っているでしょう

kill (fmap (const ()) (Kill id)) () :: Void

そして月はグリーンチーズでできています。

その間

newtype Dead x = Oops {oops :: Void}

ファンクタです

instance Functor Dead where
  fmap f (Oops corpse) = Oops corpse

しかし、適用することはできません。

oops (pure ()) :: Void

緑は月のチーズで作られます(実際に発生する可能性がありますが、夕方になってからです).

(追加の注意:VoidData.Void空のデータ型です。undefinedモノイドであることを証明するために使用しようとする場合は、unsafeCoerceそうでないことを証明するために使用します。)

喜んで、

newtype Boo x = Boo {boo :: Bool}

多くの点で適用可能です。たとえば、ダイクストラが持っているように、

instance Applicative Boo where
  pure _ = Boo True
  Boo b1 <*> Boo b2 = Boo (b1 == b2)

しかし、それはモナドにはなれません。Boo Trueなぜそうでないのかを見るために、 return が常にまたはBoo Falseでなければならないことを観察してください。

join . return == id

保持することはできません。

そうそう、忘れそうになりました

newtype Thud x = The {only :: ()}

モナドです。自分で巻いてください。

キャッチする飛行機...

于 2011-08-28T12:09:58.697 に答える
78

他の回答には、いくつかの単純で一般的な例が欠けていたと思います。

Functor であるが Applicative ではない型コンストラクター。簡単な例はペアです:

instance Functor ((,) r) where
    fmap f (x,y) = (x, f y)

Applicativeしかし、 に追加の制限を課すことなくそのインスタンスを定義する方法はありませんrpure :: a -> (r, a)特に、任意のを定義する方法はありませんr

Applicative であるが Monad ではない型コンストラクター。よく知られている例はZipListです。(これはnewtype、リストをラップしApplicative、それらに異なるインスタンスを提供する です。)

fmap通常の方法で定義されます。しかしpure、 と<*>は次のように定義されます。

pure x                    = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)

したがってpure、指定された値を繰り返して無限リストを作成し、<*>関数のリストを値のリストで圧縮します - i番目の関数をi番目の要素に適用します。(標準<*>onは、 i番目の関数をj[]番目の要素に適用するすべての可能な組み合わせを生成します。) しかし、モナドを定義する賢明な方法はありません (この投稿を参照)。


矢印はファンクター/アプリカティブ/モナドの階層にどのように適合しますか? Sam Lindley、Philip Wadler、Jeremy Yallop によるイディオムは忘却、矢は几帳面、モナドは無差別である を参照してください。MSFP 2008. (彼らはアプリカティブ ファンクターをイディオムと呼んでいます)。

Moggi のモナド、Hughes のアロー、McBride と Paterson のイディオム (applicative functor とも呼ばれる) という 3 つの計算概念の間の接続を再検討します。イディオムは型同型 A ~> B = 1 ~> (A -> B) を満たす矢印と等価であり、モナドは型同型 A ~> B = A -> (1 ~ > B)。さらに、慣用句は矢印に埋め込まれ、矢印はモナドに埋め込まれます。

于 2012-08-27T06:32:47.723 に答える
21

ファンクターではない型コンストラクターの良い例は次のとおりです。追加の制約がなければ構築できないため、Set実装できません。fmap :: (a -> b) -> f a -> f bOrd bf b

于 2011-08-29T06:59:11.220 に答える