# Function Arrow

## Implementation

``````class Fn1Arrow extends Arrow[Function1] {

def arr[B,C](f: B => C): B => C =
f

def >>>[B,C,D](f: B => C, g: C => D): B => D =
b => g(f(b))

def first[B,C,D](f: B => C): ((B,D)) => (C,D) =
bd => (f(bd._1), bd._2)

def second[B,C,D](f: B => C): ((D,B)) => (D,C) =
db => first(f)(db.swap).swap

def ***[B,C,D,E](f: B => C, g: D => E): ((B,D)) => (C,E) =
bd => (f(bd._1), g(bd._2))

def &&&[B,C,D](f: B => C, g: B => D): B => (C,D) =
b => ***(f, g)((b,b))

}``````

## Extension methods

``````class InfixFn1Arrow[B,C](f: B => C) {

def arr =
f

def >>>[D](g: C => D) =
(b: B) => g(f(b))

def first[D](bd: (B,D)) =
(f(bd._1), bd._2)

def second[D](db: (D,B)) =
first(db.swap).swap

def ***[D,E](g: D => E) =
(bd: (B,D)) => (f(bd._1), g(bd._2))

def &&&[D](g: B => D) =
(b: B) => ***(g)((b,b))

}

implicit def function1Arrow[B,C](f: B => C): InfixFn1Arrow[B,C] =
new InfixFn1Arrow(f)

implicit def function0Arrow[C](f: => C): InfixFn1Arrow[Unit,C] =
new InfixFn1Arrow(Unit => f)``````

## Example

``````.--------------------.    .------------------------.
| .---------.        |    |      .----------.      |
| | get num |---.    |    |    .-| add real |-.    |
| '---------'    \   |    |   /  '----------'  \   |    .-----------.    .-------.
|                 >--|--->|--<                  >--|--->| to string |--->| print |
| .---------.    /   |    |   \  .----------.  /   |    '-----------'    '-------'
| | get num |---'    |    |    '-| add imag |-'    |
| '---------'        |    |      '----------'      |
'--------------------'    '------------------------'``````
``````type Complex =
(Float, Float)

def show[A](a: A): String =
a.toString

val add: Float => Float => Float =
x => y => x + y

val addC: ((Complex, Complex)) => Complex =

def getC(): Complex = {

print("real: ")
val r: Float =

print("imaginary: ")
val i: Float =

(r, i)
}

val infixFn1ArrowDemo: Unit => Unit =
(getC(), getC()) >>> addC >>> show >>> println

infixFn1ArrowDemo()``````

## Demo

This file is literate Scala, and can be run using Codedown:

``````\$ curl \
https://earldouglas.com/posts/type-classes/arrow.md \
https://earldouglas.com/posts/type-classes/fn1arrow.md |
codedown scala > script.scala
\$ scala -nc script.scala
real: 1
imaginary: 2
real: 3
imaginary: 4
(4.0,6.0)``````