Arrow は Monads の一般化だと考えることができる。全てのMonadはArrowに変換することができるが、ArrowはMonadに変換できない場合がある。Arrow型を導入する目的はMonadを使う目的と同じであり、ライブラリ向けに標準的な型を用意することである。しかし、Arrow型はMonadより広範囲の概念をサポートする。Arrow型では、部分的に静的な計算（出力の一部が入力に依存しない計算）や、複数の引数を取る計算を表すことができる。Monadで上手くいくならMonadだけを使えばよいのだが、Monadが使えそうだが使えない対象に対しては、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.
3
"foo"
4
101
ちゃんと動きました。今回出てきた記号は3つある。
さて、１を足すことができるようになったので、これから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) が使われている。
{{Exercises|1=
さて、上の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.
7
この記法で、さらに長いArrowの列を定義することができる。
plusFive =
 proc a -> do b <- plusOne -< a
              c <- plusOne -< b
              d <- plusOne -< c
              e <- plusOne -< d
              plusOne -< e