矢印とは何ですか、どのように使えばいいですか?
質問
の意味を知ろうとしました。 矢印 の意味を知ろうとしましたが、よくわかりませんでした。
私はWikibooksのチュートリアルを使いました。ウィキブックの問題は、主に、そのトピックをすでに理解している人向けに書かれているように思えることだと思います。
誰か矢印が何であるか、そしてどのようにそれを使うことができるかを説明してもらえますか?
どのように解決するのですか?
チュートリアルは知りませんが、具体的な例を見ればarrowsを理解するのは一番簡単だと思います。 私が矢印の使い方を学ぶときに一番困ったのは、どのチュートリアルや例も、実際にどのようにして
を使う
を使う方法を示していないことです。 そこで、このことを念頭に置いて、私のミニチュートリアルを紹介します。 関数とユーザー定義の矢印タイプという2つの異なる矢印を調べます。
MyArr
.
-- type representing a computation
data MyArr b c = MyArr (b -> (c,MyArr b c))
1) アローは、指定された型の入力から指定された型の出力への計算である。 arrow型クラスは3つの型引数を取る: arrow型、入力型、出力型である。 arrowインスタンスのインスタンスヘッドを見てみると、以下のようになる。
instance Arrow (->) b c where
instance Arrow MyArr b c where
アロー(どちらかというと
(->)
または
MyArr
) は計算を抽象化したものです。
関数に対して
b -> c
,
b
は入力で
c
が出力です。
の場合は
MyArr b c
,
b
は入力で
c
が出力である。
2) 実際に矢印の計算を実行するには、矢印の種類に応じた関数を使用します。 関数の場合は、単に引数に関数を適用するだけです。 他のアローの場合は、別の関数が必要です(ちょうど
runIdentity
,
runState
など)。
-- run a function arrow
runF :: (b -> c) -> b -> c
runF = id
-- run a MyArr arrow, discarding the remaining computation
runMyArr :: MyArr b c -> b -> c
runMyArr (MyArr step) = fst . step
3) 矢印は入力のリストを処理するために頻繁に使用されます。 関数の場合、これらは並行して行うことができますが、いくつかの矢印の場合、任意のステップでの出力は以前の入力に依存します(例えば、入力の実行合計を維持する)。
-- run a function arrow over multiple inputs
runFList :: (b -> c) -> [b] -> [c]
runFList f = map f
-- run a MyArr over multiple inputs.
-- Each step of the computation gives the next step to use
runMyArrList :: MyArr b c -> [b] -> [c]
runMyArrList _ [] = []
runMyArrList (MyArr step) (b:bs) = let (this, step') = step b
in this : runMyArrList step' bs
これがArrowsが有用である理由の一つです。 アローは、プログラマに状態を見せることなく、暗黙的に状態を利用することができる計算モデルを提供します。 プログラマーはアロー化された計算を使用し、それらを組み合わせて洗練されたシステムを作ることができるのです。
ここに、受け取った入力の数をカウントするMyArrがあります。
-- count the number of inputs received:
count :: MyArr b Int
count = count' 0
where
count' n = MyArr (\_ -> (n+1, count' (n+1)))
ここで、関数
runMyArrList count
は長さnのリストを入力とし、1〜nのIntsのリストを返します。
私たちはまだquot;arrow"関数、つまりArrowクラスのメソッドやそれを使って書かれた関数を一切使っていないことに注意してください。
4) 上記のコードのほとんどは、各Arrowインスタンスに固有のものです[1]。 すべての
Control.Arrow
(そして
Control.Category
) は、矢印を合成して新しい矢印を作ることです。 もし、Categoryが別のクラスではなく、Arrowの一部であると仮定するならば。
-- combine two arrows in sequence
>>> :: Arrow a => a b c -> a c d -> a b d
-- the function arrow instance
-- >>> :: (b -> c) -> (c -> d) -> (b -> d)
-- this is just flip (.)
-- MyArr instance
-- >>> :: MyArr b c -> MyArr c d -> MyArr b d
は
>>>
関数は2つの矢印を受け取り、1番目の出力を2番目の入力として使用します。
これは一般的に"fanout"と呼ばれる別の演算子です。
-- &&& applies two arrows to a single input in parallel
&&& :: Arrow a => a b c -> a b c' -> a b (c,c')
-- function instance type
-- &&& :: (b -> c) -> (b -> c') -> (b -> (c,c'))
-- MyArr instance type
-- &&& :: MyArr b c -> MyArr b c' -> MyArr b (c,c')
-- first and second omitted for brevity, see the accepted answer from KennyTM's link
-- for further details.
以降
Control.Arrow
は計算を組み合わせる手段を提供するので、ここに一つの例を示します。
-- function that, given an input n, returns "n+1" and "n*2"
calc1 :: Int -> (Int,Int)
calc1 = (+1) &&& (*2)
のような関数を頻繁に見かけるようになりました。
calc1
のような関数が、複雑な折り返しや、ポインタを操作するような関数で有用であることをよく見かけます。
は
Monad
型クラスは、モナド計算を1つの新しいモナド計算に結合する手段を提供します。
>>=
関数を使って、モナド計算を一つの新しいモナド計算にまとめる手段を提供します。 同様に
Arrow
クラスは、いくつかの原始的な関数を使って、アロー化された計算を一つの新しいアロー化された計算に結合する手段を提供してくれます (
first
,
arr
そして
***
というように
>>>
と
id
をControl.Categoryから)。 また、モナドと同様、「矢印は何をするのか」という問いにも一概に答えることはできません。 それは矢印に依存します。
残念ながら、arrow のインスタンスを実際に使っている例をあまり知りません。 関数と FRP が最も一般的なアプリケーションのようです。 HXT は、思い浮かぶ唯一の重要な使用法です。
[1] 例外
count
. のインスタンスに対して同じことをするカウント関数を書くことは可能です。
ArrowLoop
.
関連
-
[解決済み] .の違いは何ですか?(ドット)と$(ドルマーク)の違いは何ですか?
-
[解決済み] フリーモナドとは何ですか?
-
[解決済み] 制約条件付き特殊化
-
[解決済み] なぜ依存型でないのか?
-
[解決済み] Haskellの「何もしない」関数、idはなぜ大量のメモリを消費するのか?
-
[解決済み] Haskellプログラムのパフォーマンス解析ツール
-
[解決済み] Haskellのドット演算子:もっと説明が欲しい
-
[解決済み] Haskellのストリクトネスポイントは何ですか?
-
[解決済み] モナドが合成の下では閉じていないことを示す具体例(証明付き)?
-
[解決済み] GHCiで関数の型宣言を明示的に行うには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】haskellでリストを逆順にする
-
[解決済み] Haskell Preludeの'const'は何のためにあるのか?
-
[解決済み] 解釈の仕方 (Eq a)
-
[解決済み] Haskell タプルをリスト化する?
-
[解決済み] Hindley-Milnerのどの部分が理解できないのでしょうか?
-
[解決済み] 読んで学ぶべき良いHaskellのソース [終了しました]。
-
[解決済み] Haskellには末尾再帰的最適化があるか?
-
[解決済み] このHaskellのコードはなぜ-Oをつけると遅くなるのですか?
-
[解決済み] なぜStringを型クラスのインスタンスにできないのですか?
-
[解決済み] モナドが合成の下では閉じていないことを示す具体例(証明付き)?