haskell - What are arrows, and how can I use them? -
i tried learn meaning of arrows, didn't understand them.
i used wikibooks tutorial. think wikibook's problem seems written understands topic.
can explain arrows , how can use them?
i don't know tutorial, think it's easiest understand arrows if @ concrete examples. biggest problem had learning how use arrows none of tutorials or examples show how use arrows, how compose them. so, in mind, here's mini-tutorial. i'll examine 2 different arrows: functions , user-defined arrow type myarr
.
-- type representing computation data myarr b c = myarr (b -> (c,myarr b c))
1) arrow calculation input of specified type output of specified type. arrow typeclass takes 3 type arguments: arrow type, input type, , output type. looking @ instance head arrow instances find:
instance arrow (->) b c instance arrow myarr b c
the arrow (either (->)
or myarr
) abstraction of computation.
for function b -> c
, b
input , c
output.
myarr b c
, b
input , c
output.
2) run arrow computation, use function specific arrow type. functions apply function argument. other arrows, there needs separate function (just runidentity
, runstate
, etc. monads).
-- run function arrow runf :: (b -> c) -> b -> c runf = id -- run myarr arrow, discarding remaining computation runmyarr :: myarr b c -> b -> c runmyarr (myarr step) = fst . step
3) arrows used process list of inputs. functions these can done in parallel, arrows output @ given step depends upon previous inputs (e.g. keeping running total of inputs).
-- run function arrow on multiple inputs runflist :: (b -> c) -> [b] -> [c] runflist f = map f -- run myarr on multiple inputs. -- each step of computation gives next step use runmyarrlist :: myarr b c -> [b] -> [c] runmyarrlist _ [] = [] runmyarrlist (myarr step) (b:bs) = let (this, step') = step b in : runmyarrlist step' bs
this 1 reason arrows useful. provide computation model can implicitly make use of state without ever exposing state programmer. programmer can use arrowized computations , combine them create sophisticated systems.
here's myarr keeps count of number of inputs has received:
-- count number of inputs received: count :: myarr b int count = count' 0 count' n = myarr (\_ -> (n+1, count' (n+1)))
now function runmyarrlist count
take list length n input , return list of ints 1 n.
note still haven't used "arrow" functions, either arrow class methods or functions written in terms of them.
4) of code above specific each arrow instance[1]. in control.arrow
(and control.category
) composing arrows make new arrows. if pretend category part of arrow instead of separate class:
-- combine 2 arrows in sequence >>> :: arrow => b c -> c d -> b d -- function arrow instance -- >>> :: (b -> c) -> (c -> d) -> (b -> d) -- flip (.) -- myarr instance -- >>> :: myarr b c -> myarr c d -> myarr b d
the >>>
function takes 2 arrows , uses output of first input second.
here's operator, commonly called "fanout":
-- &&& applies 2 arrows single input in parallel &&& :: arrow => b c -> b c' -> 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 , second omitted brevity, see accepted answer kennytm's link -- further details.
since control.arrow
provides means combine computations, here's 1 example:
-- function that, given input n, returns "n+1" , "n*2" calc1 :: int -> (int,int) calc1 = (+1) &&& (*2)
i've found functions calc1
useful in complicated folds, or functions operate on pointers example.
the monad
type class provides means combine monadic computations single new monadic computation using >>=
function. similarly, arrow
class provides means combine arrowized computations single new arrowized computation using few primitive functions (first
, arr
, , ***
, >>>
, id
control.category). similar monads, question of "what arrow do?" can't answered. depends on arrow.
unfortunately don't know of many examples of arrow instances in wild. functions , frp seem common applications. hxt other significant usage comes mind.
[1] except count
. it's possible write count function same thing instance of arrowloop
.
Comments
Post a Comment