Skip to content

Instantly share code, notes, and snippets.

@jhaberstro
Last active December 14, 2015 18:39
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jhaberstro/9aa326e3762f91abbe8f to your computer and use it in GitHub Desktop.
Save jhaberstro/9aa326e3762f91abbe8f to your computer and use it in GitHub Desktop.
Swift monoid, num, Sum typeclasses with Int32 instances
protocol Monoid {
class func mzero() -> Self
func mop(y: Self) -> Self
}
func mconcat<M : Monoid>(t: Array<M>) -> M {
return (t.reduce(M.mzero()) { $0.mop($1) })
}
protocol Num {
class func zero() -> Self
func succ() -> Self
func add(y: Self) -> Self
func multiply(y: Self) -> Self
}
// When there is only one natural typeclass definition, use extensions. This is the ideal syntax.
extension Int32: Num {
static func zero() -> Int32 { return 0 }
func succ() -> Int32 { return self + 1 }
func add(y: Int32) -> Int32 { return self + y }
func multiply(y: Int32) -> Int32 { return self * y }
}
extension String: Monoid {
static func mzero() -> String { return "" }
func mop(y: String) -> String { return self + y }
}
// When there is more than one natural typeclass (i.e. Sum and Product), create a wrapper type (à la Haskell) and manually wrap/unwrapp
struct Sum<A: Num> : Monoid {
let value: A
static func mzero() -> Sum { return Sum(value:A.zero()) }
func mop(y: Sum)-> Sum { return Sum(value: value.add(y.value)) }
}
let l : Array<Int32> = [1,2,3]
// Using only the Num typeclass to perform summation.
// Notice that we
func sum<A : Num>(xs: Array<A>) -> A {
return xs.reduce(A.zero(), { $0.add($1) })
}
println(sum(l))
// Using the Sum typeclass to perform summation
println(mconcat(l.map { Sum(value:$0) }).value)
// Another use of monoids to perform string concatenation
println(mconcat(["Hello", " ", "world!"]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment