Created
June 25, 2014 03:49
-
-
Save tLewisII/c44a70a560488edea29a to your computer and use it in GitHub Desktop.
Monoid with Dual and Writer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
operator infix <> { | |
associativity left | |
} | |
protocol Monoid { | |
typealias M | |
func mempty() -> M | |
func mappend(a:M) -> M | |
} | |
struct Dual<A:Monoid where A.M == A> :Monoid, Printable, DebugPrintable { | |
typealias M = Dual | |
let m:A | |
func mempty() -> M { | |
return Dual(m.mempty()) | |
} | |
func mappend(a: M) -> M { | |
return Dual(a.m.mappend(m)) | |
} | |
init(_ aa:A) { | |
m = aa | |
} | |
var debugDescription:String { | |
return "\(m)" | |
} | |
var description:String { | |
return "\(m)" | |
} | |
} | |
extension String : Monoid { | |
typealias M = String | |
func mempty() -> M { | |
return "" | |
} | |
func mappend(a:M) -> M { | |
return self + a | |
} | |
} | |
extension Array : Monoid { | |
typealias M = Array | |
func mempty() -> M { | |
return [] | |
} | |
func mappend(a:M) -> M { | |
var temp = Array(self) | |
for x in a { | |
temp += x | |
} | |
return Array(temp) | |
} | |
} | |
struct Writer<A, B:Monoid> { | |
let a:A | |
let s:B | |
init(_ a:A, _ s:B) { | |
self.a = a | |
self.s = s | |
} | |
static func writer(a:A, _ s:B) -> Writer<A, B> { | |
return Writer(a,s) | |
} | |
func runWriter() -> (A, B) { | |
return (a,s) | |
} | |
//return | |
static func wrap(val:A) -> Writer<A, B> { | |
return Writer(val, Array<String>() as B) | |
} | |
func logWriter() { | |
println(self.runWriter().1) | |
} | |
} | |
func <><A:Monoid where A.M == A>(lhs:A, rhs:A) -> A { | |
return lhs.mappend(rhs) | |
} | |
func >>=<A, B, C:Monoid where C.M == C>(w:Writer<A,C>, f:A -> Writer<B,C>) -> Writer<B,C> { | |
let (val1, log1) = w.runWriter() | |
let (val2, log2) = f(val1).runWriter() | |
var temp1 = log1 <> log2 | |
return Writer.writer(val2, temp1) | |
} | |
let array = [1,2,3,4] | |
let reduced = array.reduce(Writer(0, Dual(["Should be 0"]))) { | |
(let start, let reduce) in | |
return start >>= {Writer.writer($0 + reduce, Dual(["should be \($0 + reduce)"]))} | |
} | |
reduced.logWriter() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment