Introduction

編集

Arrow は Monads の一般化だと考えることができる。全てのMonadはArrowに変換することができるが、ArrowはMonadに変換できない場合がある。Arrow型を導入する目的はMonadを使う目的と同じであり、ライブラリ向けに標準的な型を用意することである。しかし、Arrow型はMonadより広範囲の概念をサポートする。Arrow型では、部分的に静的な計算(出力の一部が入力に依存しない計算)や、複数の引数を取る計算を表すことができる。Monadで上手くいくならMonadだけを使えばよいのだが、Monadが使えそうだが使えない対象に対しては、Arrowを使うべきかもしれない。

procとarrowの根

編集

まずArrowを使った記法に馴れることから始めよう。ここでは、簡単のため、最もシンプルな関数を表すArrowと、小さなサンプルプログラムを書くことにする。

それではテキストエディタを立ち上げてHaskellファイルを書いてみよう。ファイル名は、toyArrows.hsとでもしておく。

{-# LANGUAGE Arrows #-}

import Control.Arrow (returnA)

idA :: a -> a
idA = proc a -> returnA -< a

plusOne :: Int -> Int
plusOne = proc a -> returnA -< (a+1)

これがあなたの定義したはじめてのArrowだ。1番目の例は、恒等関数をArrowで表現したものであり、2番目の例は、もう少し意味のあるArrowで、入力に1を加えて出力する計算を表現するArrowである。これを -XArrows のオプションをつけてGHCiで読み込んで、何が起こるか見てみよう。

% ghci -XArrows toyArrows.hs   
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.4.1, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base-1.0 ... linking ... done.
Compiling Main             ( toyArrows.hs, interpreted )
Ok, modules loaded: Main.
*Main> idA 3
3
*Main> idA "foo"
"foo"
*Main> plusOne 3
4
*Main> plusOne 100
101

ちゃんと動きました。今回出てきた記号は3つある。

  • キーワード proc
  • Arrowの根 -<
  • インポートした関数 returnA

さて、1を足すことができるようになったので、これから2倍難しいことをやってみよう。2を足すArrowを定義する。

 plusOne = proc a -> returnA -< (a+1)
 plusTwo = proc a -> plusOne -< (a+1)

簡単な方法は、上の例のように(a+1)をplusOneArrowに入力することである。 plusOneの定義とplusTwoの定義がにていることに注目して欲しい。同じパターン proc FOO -> SOME_ARROW -< (SOMETHING_WITH_FOO) が使われている。

演習
  1. plusOne はArrowであるから上記のパターンによれば returnA もArrowに違いない。では君は returnA は何をしていると思うだろうか?

do 記法

編集

さて、上のplusTwoの定義を見て読者はがっかりしたのではないか。なぜ、plusOneを2回実行する定義になっていないのかと。ここでは、do記法を導入して、そのような定義を行ってみる。

 plusTwoBis = 
  proc a -> do b <- plusOne -< a
               plusOne -< b

GHCiで実行する。

Prelude> :r
Compiling Main             ( toyArrows.hs, interpreted )
Ok, modules loaded: Main.
*Main> plusTwoBis 5
7

この記法で、さらに長いArrowの列を定義することができる。

plusFive =
 proc a -> do b <- plusOne -< a
              c <- plusOne -< b
              d <- plusOne -< c
              e <- plusOne -< d
              plusOne -< e

Monads and arrows

編集
FIXME: I'm no longer sure, but I believe the intention here was to show what the difference is having this proc notation instead to just a regular chain of dos


このページ「Haskell/Arrows」は、まだ書きかけです。加筆・訂正など、協力いただける皆様の編集を心からお待ちしております。また、ご意見などがありましたら、お気軽にトークページへどうぞ。

テンプレート:Haskell navigation