# funflow: Quick reference

This document presents how to use the API through short examples.

This document uses the following language extensions:

In [1]:
:opt no-lint
In [2]:
{-# LANGUAGE Arrows #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

All imports are available in the Funflow module:

In [3]:
import Funflow

A minimal flow¶

In [4]:
let
  flow :: Flow String String
  flow = pureFlow $ \input -> "Hello " ++ input ++ " !"
  input :: String
  input = "Watson"
  in
    runFlow flow input :: IO String
"Hello Watson !"

Composing flows¶

In [5]:
let
  flow1 :: Flow () String
  flow1 = pureFlow $ \input -> "Hello"

  flow2 :: Flow String String
  flow2 = pureFlow $ \input -> input ++ " world"
  
  flow :: Flow () String
  flow = flow1 >>> flow2
  in
    runFlow flow () :: IO String
"Hello world"

Conditional branching¶

In [6]:
let
  increment :: Flow Int Int
  increment = pureFlow (+ 1)

  reset :: Flow Int Int
  reset = pureFlow (const 0)

  limitedIncrement :: Flow Int Int
  limitedIncrement = proc n -> do
    if n < 10
      then do increment -< n
      else reset -< n

  flow :: Flow Int Int
  flow = limitedIncrement >>> limitedIncrement >>> limitedIncrement
  in
    do
      runFlow flow (9 :: Int) :: IO Int
1

Caching a flow¶

In [7]:
let
  increment :: Flow Int Int
  increment = ioFlow $ \input -> do
    putStrLn "Increment!"
    return $ input + 1

  reset :: Flow Int Int
  reset = pureFlow $ \input -> 0

  cachedIncrement :: Flow Int Int
  cachedIncrement = caching ("increment" :: String) increment

  flow1 :: Flow Int Int
  flow1 = reset >>> increment >>> reset >>> increment

  flow2 :: Flow Int Int
  flow2 = reset >>> cachedIncrement >>> reset >>> cachedIncrement
  in
    do
    -- Prints "Increment!" twice to stdout
    runFlow flow1 (0 :: Int) :: IO Int
    -- Prints "Increment!" once to stdout
    runFlow flow2 (0 :: Int) :: IO Int
    return ()
Increment!
Increment!
Increment!

## Config

Task fields / inputs of type Configurable can be subsituted with values from environment variables or a YAML file at load time.

In [8]:
import Funflow.Config (Configurable (Literal, ConfigFromFile, ConfigFromEnv))
import Funflow.Tasks.Docker
flow3 = dockerFlow $ 
    DockerTaskConfig {
        image="alpine:latest",
        command="echo",
        args=[Arg $ Literal "foo", Arg $ ConfigFromEnv "SOME_VAR", Arg $ ConfigFromFile "someYAMLKey"]
    }