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)

Dependencies

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 =
  xy => (add(xy._1._1) *** add(xy._1._2))(xy._2._1, xy._2._2)

def getC(): Complex = {

  print("real: ")
  val r: Float =
    readLine . toFloat

  print("imaginary: ")
  val i: Float =
    readLine . toFloat

  (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/type-classes/arrow.md \
    https://earldouglas.com/type-classes/fn1arrow.md |
  codedown scala > script.scala
$ scala -nc script.scala
real: 1
imaginary: 2
real: 3
imaginary: 4
(4.0,6.0)