All Projects → witchcrafters → Quark

witchcrafters / Quark

Licence: mit
Common combinators for Elixir

Programming Languages

elixir
2628 projects
operators
16 projects

Projects that are alternatives of or similar to Quark

Rich Hickey Fanclub
"every time I watch one of his talks I feel like someone has gone in and organized my brain"
Stars: ✭ 2,815 (+908.96%)
Mutual labels:  functional-programming
Kotlinjetpackinaction
🔥🔥 Kotlin Jetpack zero to hero. 新手到高手
Stars: ✭ 264 (-5.38%)
Mutual labels:  functional-programming
Haskell Study Startup
Launch your own Haskell study group. Now.
Stars: ✭ 269 (-3.58%)
Mutual labels:  functional-programming
Shen Sources
The Official Shen Sources
Stars: ✭ 248 (-11.11%)
Mutual labels:  functional-programming
Zio
ZIO — A type-safe, composable library for async and concurrent programming in Scala
Stars: ✭ 3,167 (+1035.13%)
Mutual labels:  functional-programming
Mu Scala
Mu is a purely functional library for building RPC endpoint based services with support for RPC and HTTP/2
Stars: ✭ 266 (-4.66%)
Mutual labels:  functional-programming
Never
Never: statically typed, embeddable functional programming language.
Stars: ✭ 248 (-11.11%)
Mutual labels:  functional-programming
Underscore.py
Python port of underscore.js
Stars: ✭ 277 (-0.72%)
Mutual labels:  functional-programming
Csound Expression
Haskell Framework for Electronic Music
Stars: ✭ 257 (-7.89%)
Mutual labels:  functional-programming
Programming
Code a program in a language of your choice.
Stars: ✭ 269 (-3.58%)
Mutual labels:  functional-programming
Succinct
Discriminated unions, pattern matching and partial applications for C#
Stars: ✭ 250 (-10.39%)
Mutual labels:  functional-programming
Further
🦄🌈🍄 algebraic style composition for functional UIs
Stars: ✭ 254 (-8.96%)
Mutual labels:  functional-programming
Zio Prelude
A lightweight, distinctly Scala take on functional abstractions, with tight ZIO integration
Stars: ✭ 267 (-4.3%)
Mutual labels:  functional-programming
Funcparserlib
Recursive descent parsing library for Python based on functional combinators
Stars: ✭ 250 (-10.39%)
Mutual labels:  functional-programming
Swiftrex
Swift + Redux + (Combine|RxSwift|ReactiveSwift) -> SwiftRex
Stars: ✭ 267 (-4.3%)
Mutual labels:  functional-programming
Formatting
Type-safe, functional string formatting in Swift.
Stars: ✭ 248 (-11.11%)
Mutual labels:  functional-programming
Pfps Shopping Cart
🛒 The Shopping Cart application developed in the book "Practical FP in Scala: A hands-on approach"
Stars: ✭ 262 (-6.09%)
Mutual labels:  functional-programming
Write You A Haskell
Building a modern functional compiler from first principles. (http://dev.stephendiehl.com/fun/)
Stars: ✭ 3,064 (+998.21%)
Mutual labels:  functional-programming
Golang Tutorials
Go Tutorials - Let's get our hands really dirty by writing a lot of Golang code
Stars: ✭ 277 (-0.72%)
Mutual labels:  functional-programming
Sihl
A modular functional web framework
Stars: ✭ 267 (-4.3%)
Mutual labels:  functional-programming

Quark: Common combinators for Elixir

Build Status Inline docs Deps Status hex.pm version API Docs license

Table of Contents

Quick Start

def deps do
  [{:quark, "~> 2.3"}]
end

defmodule MyModule do
  use Quark

  # ...
end

Summary

Elixir is a functional programming language, but it lacks some of the common built-in constructs that many other functional languages provide. This is not all-together surprising, as Elixir has a strong focus on handling the complexities of concurrency and fault-tolerance, rather than deeper functional composition of functions for reuse.

Includes

  • A series of classic combinators (SKI, BCKW, and fixed-points), along with friendlier aliases
  • Fully-curried and partially applied functions
  • Macros for defining curried and partially applied functions
  • Composition helpers
    • Composition operator: <|>
  • A plethora of common functional programming primitives, including:
    • id
    • flip
    • const
    • pred
    • succ
    • fix
    • self_apply

Functional Overview

Curry

Functions

curry creates a 0-arity function that curries an existing function. uncurry applies arguments to curried functions, or if passed a function creates a function on pairs.

Macros: defcurry and defcurryp

Why define the function before currying it? defcurry and defcurryp return fully-curried 0-arity functions.

defmodule Foo do
  import Quark.Curry

  defcurry div(a, b), do: a / b
  defcurryp minus(a, b), do: a - b
end

# Regular
div(10, 2)
# => 5

# Curried
div.(10).(5)
# => 2

# Partially applied
div_ten = div.(10)
div_ten.(2)
# => 5

Partial

👑 We think that this is really the crowning jewel of Quark. defpartial and defpartialp create all arities possible for the defined function, bare, partially applied, and fully curried. This does use up the full arity-space for that function name, however.

Macros: defpartial and defpartialp

defmodule Foo do
  import Quark.Partial

  defpartial one(), do: 1
  defpartial minus(a, b, c), do: a - b - c
  defpartialp plus(a, b, c), do: a + b + c
end

# Normal zero-arity
one
# => 1

# Normal n-arity
minus(4, 2, 1)
# => 1

# Partially-applied first two arguments
minus(100, 5).(10)
# => 85

# Partially-applied first argument
minus(100).(10).(50)
# => 40

# Fully-curried
minus.(10).(2).(1)
# => 7

Pointfree

Allows defining functions as straight function composition (ie: no need to state the argument). Provides a clean, composable named functions. Also doubles as an aliasing device.

defmodule Contrived do
  import Quark.Pointfree
  defx sum_plus_one, do: Enum.sum() |> fn x -> x + 1 end.()
end

Contrived.sum_plus_one([1,2,3])
#=> 7

Compose

Compose functions to do convenient partial applications. Versions for composing left-to-right and right-to-left are provided

The operator <|> is done "the math way" (right-to-left). The operator <~> is done "the flow way" (left-to-right).

Versions on lists also available.

import Quark.Compose

# Regular Composition
sum_plus_one = fn x -> x + 1 end <|> &Enum.sum/1
sum_plus_one.([1,2,3])
#=> 7

add_one = &(&1 + 1)
piped = fn x -> x |> Enum.sum |> add_one.() end
composed = add_one <|> &Enum.sum/1
piped.([1,2,3]) == composed.([1,2,3])
#=> true

sum_plus_one = (&Enum.sum/1) <~> fn x -> x + 1 end
sum_plus_one.([1,2,3])
#=> 7

# Reverse Composition (same direction as pipe)
x200 = (&(&1 * 2)) <~> (&(&1 * 10)) <~> (&(&1 * 10))
x200.(5)
#=> 1000

add_one = &(&1 + 1)
piped = fn x -> x |> Enum.sum() |> add_one.() end
composed = (&Enum.sum/1) <~> add_one
piped.([1,2,3]) == composed.([1,2,3])
#=> true

Common Combinators

A number of basic, general functions, including id, flip, const, pred, succ, fix, and self_apply.

Classics

SKI System

The SKI system combinators. s and k alone can be combined to express any algorithm, but not usually with much efficiency.

We've aliased the names at the top-level (Quark), so you can use const rather than having to remember what k means.

 1 |> i()
#=> 1

"identity combinator" |> i()
#=> "identity combinator"

Enum.reduce([1,2,3], [42], &k/2)
#=> 3

BCKW System

The classic b, c, k, and w combinators. A similar "full system" as SKI, but with some some different functionality out of the box.

As usual, we've aliased the names at the top-level (Quark).

c(&div/2).(1, 2)
#=> 2

reverse_concat = c(&Enum.concat/2)
reverse_concat.([1,2,3], [4,5,6])
#=> [4,5,6,1,2,3]

repeat = w(&Enum.concat/2)
repeat.([1,2])
#=> [1,2,1,2]

Fixed Point

Several fixed point combinators, for helping with recursion. Several formulations are provided, but if in doubt, use fix. Fix is going to be kept as an alias to the most efficient formulation at any given time, and thus reasonably future-proof.

fac = fn fac ->
  fn
    0 -> 0
    1 -> 1
    n -> n * fac.(n - 1)
  end
end

factorial = y(fac)
factorial.(9)
#=> 362880

Sequence

Really here for pred and succ on integers, by why stop there? This works with any ordered collection via the Quark.Sequence protocol.

succ 10
#=> 11

42 |> origin() |> pred() |> pred()
#=> -2
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].