Skip to content

Commit

Permalink
feat(std): Re-export all std.map functions as implicit functions
Browse files Browse the repository at this point in the history
BREAKING CHANGE

`std.map.make` is removed, all functions are now exported directly from `std.map` with the comparator as an implicit argument
  • Loading branch information
Marwes committed Jun 7, 2018
1 parent 5047f44 commit 64bb789
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 128 deletions.
16 changes: 7 additions & 9 deletions examples/lisp/lisp.glu
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ let { Option } = import! std.option

let list @ { List, ? } = import! std.list

let map = import! std.map
let { Map } = map
let prim_map @ { ? } = map.make string.ord
let map @ { Map, ? } = import! std.map

let { Expr, Function, Lisp, LispState } = import! "examples/lisp/types.glu"
let lisp_parser = import! "examples/lisp/parser.glu"
Expand Down Expand Up @@ -105,7 +103,7 @@ let scope_state run : Lisp a -> Lisp a =

let fail msg : String -> Lisp a = lisp (\_ -> Err msg)

let primitive name f : String -> _ -> Map String Expr = prim_map.singleton name (Primitive f)
let primitive name f : String -> _ -> Map String Expr = map.singleton name (Primitive f)

type Binop a = a -> a -> a

Expand Down Expand Up @@ -140,7 +138,7 @@ let define xs =
match xs with
| Cons (Atom name) (Cons value Nil) ->
do state = get_state
let new_state = prim_map.insert name value state
let new_state = map.insert name value state
do _ = set_state new_state
wrap value
| Cons (List (Cons (Atom name) params)) body ->
Expand All @@ -152,7 +150,7 @@ let define xs =
body,
closure,
}
let new_state = prim_map.insert name function closure
let new_state = map.insert name function closure

do _ = set_state new_state

Expand All @@ -169,7 +167,7 @@ let apply f xs : Expr -> List Expr -> Lisp Expr =
let add_args names values =
match (names, values) with
| (Cons name names, Cons value values) ->
do _ = modify_state (\state -> prim_map.insert name value state)
do _ = modify_state (\state -> map.insert name value state)
add_args names values
| (Nil, _) -> wrap ()
| _ -> fail "Not enough arguments to function"
Expand All @@ -186,7 +184,7 @@ and eval_lisp expr : Expr -> Lisp Expr =
match expr with
| Atom name ->
do state = get_state
match prim_map.find name state with
match map.find name state with
| Some value -> wrap value
| None -> fail ("Binding `" <> name <> "` is not defined")
| Int _ -> wrap expr
Expand All @@ -201,7 +199,7 @@ and eval_lisp expr : Expr -> Lisp Expr =
if name == "define" then
define xs
else
match prim_map.find name state with
match map.find name state with
| Some prim ->
do evaluated_args = traverse eval_lisp xs
apply prim evaluated_args
Expand Down
4 changes: 1 addition & 3 deletions repl/src/repl.glu
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
let prelude = import! std.prelude
let io @ { ? } = import! std.io
let map @ { Map } = import! std.map
let map @ { Map, empty, singleton, find, insert, ? } = import! std.map
let { Bool } = import! std.bool
let { Option } = import! std.option
let { Result } = import! std.result
Expand All @@ -17,10 +17,8 @@ let { (<<) } = import! std.function
let { Applicative, wrap, (*>) } = import! std.applicative
let { flat_map, (>>=) } = import! std.monad

let ord_map @ { singleton, find, insert, ? } = map.make string.ord
let { (<>) } = import! std.prelude
let (++) = (<>)
let { empty } = ord_map.monoid


let run_interruptible_io cpu_pool action : CpuPool -> IO String -> IO (Result String String) =
Expand Down
11 changes: 6 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,14 +620,15 @@ impl Compiler {

pub const PRELUDE: &'static str = r#"
let __implicit_prelude = import! std.prelude
and { Num, Eq, Ord, Show, Functor, Applicative, Monad, ? } = __implicit_prelude
and { Bool, not, ? } = import! std.bool
and { Option, ? } = import! std.option
and { Num, Eq, Ord, Show, Functor, Applicative, Monad, Option, Bool, ? } = __implicit_prelude
let { (+), (-), (*), (/), (==), (/=), (<), (<=), (>=), (>), show, ? } = __implicit_prelude
let { (+), (-), (*), (/), (==), (/=), (<), (<=), (>=), (>), show, not } = __implicit_prelude
let __implicit_float @ { ? } = import! std.float
let __implicit_bool @ { ? } = import! std.bool
let { ? } = import! std.option
let __implicit_float @ { ? } = import! std.float
let __implicit_int @ { ? } = import! std.int
Expand Down
4 changes: 2 additions & 2 deletions std/applicative.glu
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ let empty ?alt : [Alternative f] -> f a = alt.empty

let or ?alt : [Alternative f] -> f a -> f a -> f a = alt.or

/// Alias of `or`
/// Alias of `or`
#[infix(left, 3)]
let (<|>): [Alternative f] -> f a -> f a -> f a = or
let (<|>) : [Alternative f] -> f a -> f a -> f a = or


{
Expand Down
2 changes: 1 addition & 1 deletion std/cmp.glu
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ let (<=) l r : [Ord a] -> a -> a -> Bool =
| GT -> False

#[infix(left, 4)]
let (<) l r : [Ord a] -> a -> a -> Bool =
let (<) ?x l r : [Ord a] -> a -> a -> Bool =
match compare l r with
| LT -> True
| EQ -> False
Expand Down
210 changes: 112 additions & 98 deletions std/map.glu
Original file line number Diff line number Diff line change
Expand Up @@ -8,111 +8,125 @@ let { Traversable } = import! std.traversable
let { flip, const } = import! std.function
let list @ { List } = import! std.list
let { Option } = import! std.option
let { compare } = import! std.cmp

type Map k a =
| Bin k a (Map k a) (Map k a)
| Tip

/// The empty map.
let empty = Tip

/// Creates a map with a single entry.
let singleton k v = Bin k v empty empty

let make ord : Ord k -> _ =
let find k m : k -> Map k a -> Option a =
/// Searches the map `m` for `k`. Returns `Some` with the element if it is found and otherwise `None`.
let find k m : [Ord k] -> k -> Map k a -> Option a =
match m with
| Bin k2 v l r ->
match compare k k2 with
| LT -> find k l
| EQ -> Some v
| GT -> find k r
| Tip -> None

/// Inserts the value `v` at the key `k` in the map `m`. If the key already exists in the map the current value gets replaced.
let insert k v m : [Ord k] -> k -> a -> Map k a -> Map k a =
match m with
| Bin k2 v2 l r ->
match compare k k2 with
| LT -> Bin k2 v2 (insert k v l) r
| EQ -> Bin k v l r
| GT -> Bin k2 v2 l (insert k v r)
| Tip -> Bin k v empty empty

let map f m : [Ord k] -> (a -> b) -> Map k a -> Map k b =
match m with
| Tip -> Tip
| Bin k x l r -> Bin k (f x) (map f l) (map f r)

/// Performs a map over the `Map` where the key gets passed to the function in additon to the value.
let map_with_key f m : [Ord k] -> (k -> a -> b) -> Map k a -> Map k b =
match m with
| Tip -> Tip
| Bin k x l r -> Bin k (f k x) (map_with_key f l) (map_with_key f r)

let foldr f z m : [Ord k] -> (a -> b -> b) -> b -> Map k a -> b =
match m with
| Tip -> z
| Bin _ x l r -> foldr f (f x (foldr f z r)) l

let foldl f z m : [Ord k] -> (a -> b -> a) -> a -> Map k b -> a =
match m with
| Tip -> z
| Bin _ x l r -> foldl f (f (foldl f z l) x) r

let foldr_with_key f z m : [Ord k] -> (k -> a -> b -> b) -> b -> Map k a -> b =
match m with
| Tip -> z
| Bin k v l r -> foldr_with_key f (f k v (foldr_with_key f z r)) l

/// Performs a fold over the `Map` where the key gets passed to the function in addition to the value.
let foldl_with_key f z m : [Ord k] -> (a -> k -> b -> a) -> a -> Map k b -> a =
match m with
| Tip -> z
| Bin k x l r -> foldl_with_key f (f (foldl_with_key f z l) k x) r

/// Performs a traverse over the `Map` where the key gets passed to the function in addition to the value.
let traverse_with_key app f m : [Ord k] -> Applicative t
-> (k -> a -> t b)
-> Map k a
-> t (Map k b)
=
let { map3 } = import! std.applicative

let go m =
match m with
| Bin k2 v l r ->
match ord.compare k k2 with
| LT -> find k l
| EQ -> Some v
| GT -> find k r
| Tip -> None

let insert k v m : k -> a -> Map k a -> Map k a =
match m with
| Bin k2 v2 l r ->
match ord.compare k k2 with
| LT -> Bin k2 v2 (insert k v l) r
| EQ -> Bin k v l r
| GT -> Bin k2 v2 l (insert k v r)
| Tip -> Bin k v empty empty

let map f m : (a -> b) -> Map k a -> Map k b =
match m with
| Tip -> Tip
| Bin k x l r -> Bin k (f x) (map f l) (map f r)

let map_with_key f m : (k -> a -> b) -> Map k a -> Map k b =
match m with
| Tip -> Tip
| Bin k x l r -> Bin k (f k x) (map_with_key f l) (map_with_key f r)

let foldr f z m : (a -> b -> b) -> b -> Map k a -> b =
match m with
| Tip -> z
| Bin _ x l r -> foldr f (f x (foldr f z r)) l

let foldl f z m : (a -> b -> a) -> a -> Map k b -> a =
match m with
| Tip -> z
| Bin _ x l r -> foldl f (f (foldl f z l) x) r

let foldr_with_key f z m : (k -> a -> b -> b) -> b -> Map k a -> b =
match m with
| Tip -> z
| Bin k v l r -> foldr_with_key f (f k v (foldr_with_key f z r)) l

let foldl_with_key f z m : (a -> k -> b -> a) -> a -> Map k b -> a =
match m with
| Tip -> z
| Bin k x l r -> foldl_with_key f (f (foldl_with_key f z l) k x) r

let traverse_with_key app f m : Applicative t -> (k -> a -> t b) -> Map k a -> t (Map k b) =
let { map3 } = import! std.applicative

let go m =
match m with
| Tip -> app.wrap Tip
| Bin k v l r ->
map3 (flip (Bin k)) (go l) (f k v) (go r)

go m

let traverse app f : Applicative t -> (a -> t b) -> Map k a -> t (Map k b) =
traverse_with_key app (const f)

let append l r : Map k a -> Map k a -> Map k a = foldr_with_key insert l r

let semigroup : Semigroup (Map k a) = { append }
let monoid : Monoid (Map k a) = { semigroup, empty }

let functor : Functor (Map k) = { map }
let foldable : Foldable (Map k) = { foldr, foldl }
let traversable : Traversable (Map k) = { functor, foldable, traverse }

let to_list : Map k a -> List { key : k, value : a } =
foldr_with_key (\key value acc -> Cons { key, value } acc) Nil

let keys : Map k a -> List k = foldr_with_key (\k _ acc -> Cons k acc) Nil

let values : Map k a -> List a = foldr Cons Nil

{
semigroup,
monoid,
functor,
foldable,
traversable,
singleton,
empty,
find,
insert,
map_with_key,
foldr_with_key,
foldl_with_key,
traverse_with_key,
to_list,
keys,
values,
}

{ Map, make }
| Tip -> app.wrap Tip
| Bin k v l r ->
map3 (flip (Bin k)) (go l) (f k v) (go r)

go m

let traverse app f : [Ord k] -> Applicative t -> (a -> t b) -> Map k a -> t (Map k b) =
traverse_with_key app (const f)

/// Combines two maps into one. If a key exists in both maps the value in `r` takes precedence.
let append l r : [Ord k] -> Map k a -> Map k a -> Map k a = foldr_with_key insert l r

let semigroup : [Ord k] -> Semigroup (Map k a) = { append }
let monoid : [Ord k] -> Monoid (Map k a) = { semigroup, empty }

let functor : [Ord k] -> Functor (Map k) = { map }
let foldable : [Ord k] -> Foldable (Map k) = { foldr, foldl }
let traversable : [Ord k] -> Traversable (Map k) = { functor, foldable, traverse }

let to_list : [Ord k] -> Map k a -> List { key : k, value : a } =
foldr_with_key (\key value acc -> Cons { key, value } acc) Nil

/// Returns a list of all keys in the map.
let keys : [Ord k] -> Map k a -> List k = foldr_with_key (\k _ acc -> Cons k acc) Nil

/// Returns a list of all values in the map.
let values : [Ord k] -> Map k a -> List a = foldr Cons Nil

{
Map,

semigroup,
monoid,
functor,
foldable,
traversable,
singleton,
empty,
find,
insert,
map_with_key,
foldr_with_key,
foldl_with_key,
traverse_with_key,
to_list,
keys,
values,
}
2 changes: 1 addition & 1 deletion std/prelude.glu
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ let { error } = import! std.prim
Bool,

not,

error,
}
1 change: 1 addition & 0 deletions std/result.glu
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let { Bool } = import! std.bool
let { compare } = import! std.cmp
let string @ { ? } = import! std.string
let { (<>) } = import! std.semigroup
let { error } = import! std.prim

let unwrap_ok res : Result e a -> a =
match res with
Expand Down
1 change: 1 addition & 0 deletions std/test.glu
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ let list @ { List, ? } = import! std.list
let { Foldable, foldl } = import! std.foldable
let { Option } = import! std.option
let { (<>) } = import! std.semigroup
let { error } = import! std.prim


type Test a = Writer (List String) a
Expand Down
6 changes: 1 addition & 5 deletions tests/pass/map.glu
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ let option @ { Option } = import! std.option
let string = import! std.string
let { (<>) } = import! std.prelude
let { Test, run, assert, assert_eq, test, group, ? } = import! std.test
let map @ { ? } = import! std.map
let map @ { empty, singleton, find, insert, to_list, keys, values, ? } = import! std.map
let { Applicative, (*>) } = import! std.applicative
let list @ { List, ? } = import! std.list

Expand All @@ -17,10 +17,6 @@ let eq_Entry : Eq { key : String, value : Int } = {
(==) = \l r -> l.key == r.key && l.value == r.value
}

let ord_map = map.make string.ord
let { singleton, find, insert, to_list, keys, values, ? } = ord_map
let { empty } = ord_map.monoid

let basic_tests =
let test_map = singleton "test" 1 <> singleton "asd" 2 <> singleton "a" 3

Expand Down
Loading

0 comments on commit 64bb789

Please sign in to comment.