unisonweb/unison

started on map-reduce example, hit a bunch of bugs along the way

pchiusano committed Aug 3, 2018
1 parent 027539b commit 30dcb4ccd7a9edf247804a0eab6321c78daaa18e
Showing with 94 additions and 0 deletions.
1. +94 −0 unison-src/map-reduce.u
@@ -0,0 +1,94 @@

-- A simple distributed computation effect
effect Remote n where

-- Spawn a new node, of type `n`

atacratic Aug 4, 2018

Contributor

I understood this better when I read it as 'Spawn a new node, with identifier of type `n`'. Maybe tweak the comment?

spawn : {Remote n} n

-- Sequentially evaluate the given thunk on another node
at : n -> '{Remote n} a -> {Remote n} a

atacratic Aug 4, 2018

Contributor

(You're not using `at` in this example at the moment.)

-- Start a computation running, returning an `r` that can be forced to
-- await the result of the computation
fork : '{Remote n} a -> {Remote n} ('{Remote n} a)

type Monoid a = Monoid a (a -> a -> a)

use UInt64 + - * / ==
use Sequence halve map take drop size
use Optional None Some
use Monoid.Monoid -- import the constructor
use Remote fork spawn at

namespace Monoid where

zero : Monoid a -> a
zero m = case m of Monoid z _ -> z

op : Monoid a -> a -> a -> a
op m = case m of Monoid _ op -> op

fold-map : (a -> {e} b) -> Monoid b -> [a] -> {e} b
fold-map f m =
z = zero m
op = Monoid.op m
go as = case halve as of
None -> zero m
Some (l, r) -> go l `op` go r
go

atacratic Aug 4, 2018

Contributor

You're not actually using `f` in this function :-) I think you need a case to handle getting down to single-element lists.

atacratic Aug 4, 2018

Contributor

Also maybe it would work to use the existing Sequence.halve directly - matching on ([], []) instead of None.

par : Monoid a -> Monoid ('{Remote n} a)
par m = Monoid '(zero m) _ -- (par-apply (op m)) -- doesn't typecheck

ex : '{Remote n} UInt64
ex = delay
alice = spawn
bob = spawn
f1 = fork '(1 + 1)
f2 = fork '(2 + 2)
_ -- !f1 + !f2 -- doesn't typecheck

par-apply : (a -> b -> c) -> '{Remote n} a -> '{Remote n} b -> {Remote n} c
par-apply f a b =
x = fork a
y = fork b
_ -- f !x !y -- doesn't typecheck

map-reduce : (a -> {Remote n} b) -> Monoid b -> [a] -> {Remote n} b
map-reduce f m = _
-- doesn't typecheck, but should just be:
-- Monoid.fold-map f (a -> fork '(f a)) (Monoid.par m)

atacratic Aug 4, 2018

Contributor

I don't think it helps to use `fork` here, given the forking going on in `par-apply`?

-- this currently crashes the compiler
--Remote.run-local : '{Remote UInt64} a -> a
--Remote.run-local r =
-- step : UInt64 -> Effect (Remote UInt64) a -> a
-- step nid r = case r of
-- {a} -> a
-- {Remote.fork t -> k} -> handle (step nid) in (k t)
-- {Remote.spawn -> k} -> handle (step (nid + 1)) in (k nid)
--
-- handle (step 0) in !r

uno : '{e} a -> '{e} a -> {e} a
uno a a2 = !a

dos : (a -> a -> a) -> '{e} a -> '{e} a -> {e} a
dos f a a2 = f !a !a2

(<|) : (i -> o) -> i -> o
f <| i = f i
i |> f = f i

halve : [a] -> Optional ([a], [a])
halve s =
n = size s
if n == 0 then Optional.None
else
m = n / 2
Optional.Some (take m s, drop m s)

Stream.from-uint64 1
|> Stream.take 15
|> Stream.to-sequence