Haskell:<*>はどのように発音されますか?[閉まっている]


109

Applicativeタイプクラスでこれらの関数をどのように発音しますか?

(<*>) :: f (a -> b) -> f a -> f b
(*>)  :: f a -> f b -> f b
(<*)  :: f a -> f b -> f a

(つまり、演算子でなかった場合、何と呼ばれますか?)

余談ですがpure、非数学者にとってよりフレンドリーな名前に変更できるとしたら、それを何と呼びますか?


6
@Jクーパー...私たちがそれをどのように発音するか聞いていただけますか?:) meta.stackoverflow.comに音声録音および再生機能のリクエストを投稿したい場合があります:)。
キリル

8
「良い悲しみ、彼らは本当にオペレーターを使い果たしていましたね」と発音されています。また、の良い名前はpureかもしれませんmakeApplicative
Chuck

@Lirik、まあ、私は@Chuckは、あなたの投稿:)私は、「この事を呼んwhaddya」を意味発音によって推測pure答えとして提案し、私はあなたをupvoteよ
Jクーパー

6
(<*>)はControl.Monadの "ap"のControl.Applicativeバージョンなので、 "ap"がおそらく最も適切な名前です。
Edward KMETT 2010

11
私はそれをサイクロプスと呼びますが、それは私だけです。
RCIX、2010

回答:


245

申し訳ありませんが、私は自分の数学を本当に知らないので、Applicative型クラスの関数の発音方法に興味があります

あなたの数学を知っているかどうかは、ここではほとんど関係がないと思います。おそらくご存じのとおり、Haskellは、抽象的な数学のさまざまな分野、特にカテゴリ理論からいくつかの用語を借りており、そこからファンクタとモナドを取得しています。Haskellでのこれらの用語の使用は、正式な数学的定義とは多少異なりますが、通常、いずれにしても、それらは十分に説明的な用語になるほど十分に近いものです。

Applicative型クラスは、間のどこかに座っているFunctorMonad1が、それは同様の数学的基礎を持っていることを期待するので、。Control.Applicativeモジュールのドキュメントは次で始まります:

このモジュールは、ファンクターとモナドの中間の構造を記述します。純粋な式とシーケンスを提供しますが、バインディングは提供しません。(技術的には、強力で緩やかなモノイド関数です。)

うーん。

class (Functor f) => StrongLaxMonoidalFunctor f where
    . . .

ほどキャッチーMonadではないと思います。

基本的にこれがまとめると、数学的にApplicative特に興味深い概念に対応していないため、Haskellでの使用方法を表す既成の用語はありません。だから、今のところ数学を脇に置いてください。


何を呼び出すかを知りたい場合(<*>)、それが基本的に何を意味するかを知るのに役立つかもしれません。

Applicativeとにかく、何が起こっているのですか、なぜそれをそれと呼ぶのですか?

どのようなApplicative実際にになることは持ち上げるための方法である任意に機能をFunctorMaybe(おそらく最も単純な非自明なFunctor)とBool(同様に最も単純な非自明なデータ型)の組み合わせを検討してください。

maybeNot :: Maybe Bool -> Maybe Bool
maybeNot = fmap not

この関数はfmap、私たちが持ち上げることができますnotに取り組んでからBool、作業へMaybe Bool。しかし、持ち上げたい場合はどう(&&)でしょうか?

maybeAnd' :: Maybe Bool -> Maybe (Bool -> Bool)
maybeAnd' = fmap (&&)

まあ、それは我々が望むものではありませんすべてで!実際、それはほとんど役に立ちません。私たちは賢くなり、背中から別の人Boolに忍び込むことができMaybeます...

maybeAnd'' :: Maybe Bool -> Bool -> Maybe Bool
maybeAnd'' x y = fmap ($ y) (fmap (&&) x)

...しかし、それは良くありません。一つには、それは間違っています。もう1つ、醜いです。引き続き試すことはできますが、複数の引数の関数を持ち上げて任意ので機能させる方法はないことがわかりましたFunctor。迷惑!

一方、MaybeMonadインスタンスを使用すると、簡単に実行できます。

maybeAnd :: Maybe Bool -> Maybe Bool -> Maybe Bool
maybeAnd x y = do x' <- x
                  y' <- y
                  return (x' && y')

さて、単純な関数を変換するだけで、それは多くの手間です。Control.Monadこれが、自動的に実行する関数を提供する理由liftM2です。名前の2は、正確に2つの引数を持つ関数で機能することを示しています。同様の関数が3、4、および5の引数関数に存在します。これらの関数は優れていますが、完全ではなく、引数の数を指定することは醜く不器用です。

これにより、Applicative型クラスを紹介した論文が表示されます。その中で、著者は本質的に2つの観察をします:

  • 複数の引数を持つ関数をに持ち上げるFunctorことは、非常に自然なことです
  • そうすることは、の完全な機能を必要としません Monad

通常の関数のアプリケーションは、用語の単純な並置によって記述されるため、「リフトアプリケーション」を可能な限りシンプルかつ自然にするために、このペーパーでは、アプリケーションに代わるインフィックス演算子をFunctor紹介し、にリフトアップし、そのために必要なものを提供するタイプクラスを紹介します。

これらすべてが次のポイントに私たちをもたらします:(<*>)単に関数の適用を表します-それで、なぜあなたが空白の「並置演算子」をするのと違うようにそれを発音するのですか?

しかし、それがあまり満足できない場合は、Control.Monadモジュールがモナドに対して同じことを行う関数も提供していることがわかります。

ap :: (Monad m) => m (a -> b) -> m a -> m b

ここでap、当然のことながら、「適用」の略です。いずれか以来MonadすることができApplicative、そしてap後者に存在する機能のサブセットのみを必要とする、我々は、おそらくと言うことができるならば(<*>)、オペレータはなかった、それが呼ばれるべきap


他の方向からもアプローチできます。Functor昇降操作が呼び出されfmap、それはの一般化だからmapリストの操作。リストではどのような関数が機能します(<*>)か?apもちろん、リストには何がありますが、それだけでは特に役に立ちません。

実際、リストにはおそらくもっと自然な解釈があります。次の型シグネチャを見ると、何が思い浮かびますか?

listApply :: [a -> b] -> [a] -> [b]

リストを並列に並べ、最初の各関数を2番目の対応する要素に適用するというアイデアには、とても魅力的なものがあります。古くからの友人にとって残念なことにMonad、この単純な操作、リストの長さが異なる場合、モナドの法則に違反します。しかし、それは問題Applicativeありません。その場合、の汎用バージョンをつなぎ合わせる(<*>)方法になるので、おそらくそれを呼び出すことを想像できますか?zipWithfzipWith


このジッパーのアイデアは、実際に私たちを一周します。モノイド関数については、以前の数学のことを思い出してください。名前が示すように、これらはモノイドとファンクタの構造を組み合わせる方法です。どちらもおなじみのHaskell型クラスです。

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

class Monoid a where
    mempty :: a
    mappend :: a -> a -> a

これらを一緒に箱に入れて少し振ると、どのように見えますか?Functor我々はのアイデアおこう、その型パラメータの構造から独立して、からMonoid私たちは機能の全体的な形をしておこう:

class (Functor f) => MonoidalFunctor f where
    mfEmpty :: f ?
    mfAppend :: f ? -> f ? -> f ?

真に「空」を作成する方法があると想定したくはありませんFunctor。また、任意の型の値を呼び出すことができないため、mfEmptyas の型を修正しますf ()

またmfAppend、一貫性のある型パラメーターを強制的に必要としないため、次のようになります。

class (Functor f) => MonoidalFunctor f where
    mfEmpty :: f ()
    mfAppend :: f a -> f b -> f ?

の結果タイプはmfAppend何ですか?何も知らない任意のタイプが2つあるため、多くのオプションはありません。最も賢明なことは、両方を保持することです。

class (Functor f) => MonoidalFunctor f where
    mfEmpty :: f ()
    mfAppend :: f a -> f b -> f (a, b)

その時点mfAppendで明らかzipにリストの一般化されたバージョンになり、Applicative簡単に再構築できます。

mfPure x = fmap (\() -> x) mfEmpty
mfApply f x = fmap (\(f, x) -> f x) (mfAppend f x)

これpureは、のID要素に関連していることも示しているMonoidため、他の適切な名前は、ユニット値、null演算などを示唆するものである可能性があります。


それは長いので、要約すると:

  • (<*>) は単に変更された関数アプリケーションなので、「ap」または「apply」として読み取るか、通常の関数アプリケーションとまったく同じ方法で省略できます。
  • (<*>)またzipWith、リストをおおまかに一般化しているため、「zip functors with」と読むことができますfmap。「map a functor with」と読むのと同じです。

1つ目はApplicative、名前が示すように、型クラスの意図に近いため、これをお勧めします。

実際、私はすべての解除されたアプリケーションオペレーターの寛大な使用と非発音を奨励します

  • (<$>)、これは単一引数関数を Functor
  • (<*>)、複数の引数を持つ関数を Applicative
  • (=<<)、を入力する関数をMonad既存の計算にバインドします

3つすべては、基本的に、通常の関数アプリケーションであり、少しスパイスが効いています。


6
@Colin Cochrane:そこに「長続きする」スペルミスがないと確信していますか :)しかし、ちょっと、私はそれを取ります!私はいつもApplicative、それが促進する機能的な慣用的なスタイルでは十分な愛情を得られないので、自分の発音を説明する方法として(そうではない)説明する手段として、その美徳を賞賛する機会に少しは抵抗できませんでした(<*>)
2010


6
Haskellにはの構文糖があったでしょうかApplicative[| f a b c d |](元の論文で示唆されているように)次に、<*>コンビネータは必要なく、「式の関数アプリケーション」の例としてこのような式を参照します
Tom Crockett

1
@FredOverflow:いいえ、意味しましたMonad。またはFunctorまたはMonoidまたはより少ない3つの形容詞を含む十分に確立用語を持っている何か。「Applicative」は、合理的に説明的ではありますが、どちらかと言えば必要なものに付け加えられた、単に刺激的ではない名前です。
カリフォルニア州マッキャン、2011

1
@pelotom:[ stackoverflow.com/questions/12014524/…を参照してください。親切な人々が私に2つの方法でほとんどその表記を取得する方法を示しました。
AndrewC 2012

21

私はCAマッキャンの技術的回答を改善するという野心がないので、もっとふわふわなものに取り組みます。

pure私のようなポダンクにもっとフレンドリーな名前に変更できるとしたら、それを何と呼びますか?

別の方法として、特にMonadreturn」と呼ばれるバージョンに対する絶え間ない怒りと裏切りに満ちた叫びに終わりがないので、私は別の名前を提案します。 、そして最も機能的な...まあ、うまくいけば、誰もが同じことについて文句を言うことができます:inject

値を取る。「注入」そこにFunctorApplicativeMonad、または何-てい-ます。「inject」に投票し、このメッセージを承認しました。


4
私は通常「ユニット」や「リフト」のようなものに傾いていますが、Haskellにはすでに他の意味が多すぎます。injectマイナーな補足として、「inject」は、SmalltalkとRubyで使用されています。名前の選択を理解したことはありませんが...
CA McCann 2010

3
これは非常に古いスレッドですがinject、Ruby&Smalltalkでは、リストの各要素の間に演算子を「挿入」しているように見えるので、これが使用されていると思います。少なくとも、私はいつもそう思っていました。
ジョナサンスターリング

1
その古いサイドスレッドを再び取り上げるには、演算子を注入するのではなく、すでにそこにあるコンストラクターを置き換える(排除する)ことになります。(逆に見ると、古いデータを新しいタイプに注入していることになります。)リストの場合、消去は単にfoldrです。(あなたは置き換える(:)[]、どこ(:)2つの引数を取り、[]それゆえ、一定であるfoldr (+) 0 (1:2:3:[])1+2+3+0。)にはBool、それだけだif- then- else(2つの定数、1を選択)とのためにMaybeそれを呼び出してmaybe、すべての異なる種類を持っているよう... Haskellは、このための単一の名前/機能を持っていません(一般的にelimは単なる再帰/帰納です)
誰も

@CAMcCann Smalltalkは、ベトナム戦争のドラフトに関するArlo Guthrieの歌からその名前を得ました。そこでは、不幸な若い男性が集められ、選ばれ、時には拒否され、そしてその他の形で注射されました。
トムアンダーソン

7

簡単に言えば:

  • <*>あなたはそれを適用と呼ぶことができます。したがってMaybe f <*> Maybe aapply Maybe foverMaybe aと発音できます。

  • 多くのJavaScriptライブラリと同じようpureof、名前をに変更できます。JSでは、Maybewith を作成できますMaybe.of(a)

また、Haskellのwikiには、言語の演算子の発音上のページがあり、ここで


3
(<*>) -- Tie Fighter
(*>)  -- Right Tie
(<*)  -- Left Tie
pure  -- also called "return"

出典:クリスアレンとジュリーモロヌキによるHaskell Programming from First Principles


私の知る限り、これらの名前は正確に理解されていません。
dfeuer 2016年

@dfeuerは、その本を主要な学習資料として使用している次世代のHaskellerを待ちます。
dmvianna 2016年

1
それは起こり得る。ただし、名前は意味とは関係がないため、ひどいです。
dfeuer 2016年

1
@dfeuer、私はどこにも良い解決策を見ていません。「ap」/「apply」は「tie fighter」と同じくらいあいまいです。すべてが機能アプリです。しかし、突然生まれた名前は、使用を通じて意味を獲得することができます。「アップル」が良い例です。ちなみに、モナドリターン Applicativeのみです。ここには発明はありません。
dmvianna 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.