Skip to content

Commit

Permalink
Remove return function on Monad
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanzab committed Jul 22, 2016
1 parent 4d4daea commit e893f50
Show file tree
Hide file tree
Showing 19 changed files with 91 additions and 102 deletions.
2 changes: 1 addition & 1 deletion src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ pub fn load(vm: &Thread) -> Result<()> {
vm.add_bytecode("io_bind", io_bind_type, 3, io_bind);


vm.add_bytecode("io_return",
vm.add_bytecode("io_pure",
<fn(A) -> IO<A> as VMType>::make_type(vm),
2,
vec![Pop(1)]);
Expand Down
61 changes: 29 additions & 32 deletions std/prelude.glu
Original file line number Diff line number Diff line change
Expand Up @@ -405,60 +405,57 @@ let make_Alternative fun app alt =
}

type Monad m = {
(>>=) : m a -> (a -> m b) -> m b,
return : a -> m a
(>>=) : m a -> (a -> m b) -> m b
}

let monad_Function: Monad ((->) a) = {
(>>=) = \m f x -> f (m x) x,
return = applicative_Function.pure
(>>=) = \m f x -> f (m x) x
}

let monad_Option: Monad Option = {
(>>=) = \m f -> match m with
| Some x -> f x
| None -> None,
return = \x -> Some x
| None -> None
}

let monad_List: Monad List = {
(>>=) = \m f -> concatMap f m,
return = \x -> Cons x Nil
(>>=) = \m f -> concatMap f m
}

let monad_IO: Monad IO = {
(>>=) = io_bind,
return = io_return
(>>=) = io_bind
}

let make_Monad m =
let { (>>=), return } = m
let make_Monad m app =
let { (>>=) } = m
// let { pure } = app // fails to typecheck on usage! :s
let { id } = category_Function

let (>>) l r = l >>= \_ -> r
let forM_ xs f =
let (>>) l r : m a -> m b -> m b = l >>= \_ -> r
let join mm : m (m a) -> m a = mm >>= id
let lift2 f lm rm = lm >>= \l -> rm >>= \r -> f l r
let forM_ xs f : List a -> (a -> m b) -> m () =
match xs with
| Cons y ys -> f y >> forM_ ys f
| Nil -> return ()
{
(>>=),
return = return,
(>>),
join = \mm -> mm >>= id,
map = \x f -> x >>= (\y -> return (f x)),
lift2 = \f lm rm -> lm >>= \l -> rm >>= \r -> f l r,
forM_
}
| Nil -> app.pure ()

let functor_IO: Functor IO = {
map = \f m1 -> monad_IO.(>>=) m1 (\x -> monad_IO.return (f x))
}
{ (>>=), (>>), join, lift2, forM_ }

let applicative_IO: Applicative IO = {
(<*>) = \f x ->
monad_IO.(>>=) f (\g -> monad_IO.(>>=) x (\y -> monad_IO.return (g y))),
pure = monad_IO.return
}
let applicative_IO: Applicative IO =
let { (>>=) } = monad_IO

let pure = io_pure
let (<*>) f x = f >>= (\g -> x >>= (\y -> pure (g y)))

{ (<*>), pure }

let functor_IO: Functor IO =
let { pure } = applicative_IO
let { (>>=) } = monad_IO

let map f m1 = m1 >>= (\x -> pure (f x))

{ map }

/// The identity function, where `id x == x`
let id : a -> a =
Expand Down
35 changes: 18 additions & 17 deletions std/repl.glu
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ let prelude = import "std/prelude.glu"
let map = import "std/map.glu"
let string = import "std/string.glu"
let { Map } = map
let { (>>=), return, (>>), forM_ } = prelude.make_Monad prelude.monad_IO
let { pure } = prelude.applicative_IO
let { (>>=), (>>), forM_ } = prelude.make_Monad prelude.monad_IO prelude.applicative_IO
let { Eq, Result, Monoid } = prelude
let { (<>) = (++) } = string.monoid
let { singleton, find, monoid, to_list } = map.make string.ord
Expand All @@ -15,11 +16,11 @@ let load_file filename: String -> IO String =
| None -> 0
| Some i -> i + 1
let modulename = string.slice filename last_slash (string.length filename - 3)
let read_result = io.catch (io.read_file_to_string filename >>= \x -> return (Ok x)) (\err -> return (Err err))
let read_result = io.catch (io.read_file_to_string filename >>= \x -> pure (Ok x)) (\err -> pure (Err err))
read_result >>= \result ->
match result with
| Ok expr -> io.load_script modulename expr
| Err msg -> return msg
| Err msg -> pure msg

type Cmd = {
info: String,
Expand All @@ -34,22 +35,22 @@ let commands: Map String Cmd =

let commands = ref empty
let cmds =
singleton "q" { info = "Quit the REPL", action = \_ -> return False }
singleton "q" { info = "Quit the REPL", action = \_ -> pure False }
<> singleton "t" {
info = "Prints the type with an expression",
action = \arg -> repl_prim.type_of_expr arg >>= print_result >> return True
action = \arg -> repl_prim.type_of_expr arg >>= print_result >> pure True
}
<> singleton "i" {
info = "Prints information about the given name",
action = \arg -> repl_prim.find_info arg >>= print_result >> return True
action = \arg -> repl_prim.find_info arg >>= print_result >> pure True
}
<> singleton "k" {
info = "Prints the kind with the given type",
action = \arg -> repl_prim.find_kind arg >>= print_result >> return True
action = \arg -> repl_prim.find_kind arg >>= print_result >> pure True
}
<> singleton "l" {
info = "Loads the file at 'folder/module.ext' and stores it at 'module'",
action = \arg -> load_file arg >>= io.print >> return True
action = \arg -> load_file arg >>= io.print >> pure True
}
<> singleton "h" {
info = "Print this help",
Expand All @@ -60,7 +61,7 @@ let commands: Map String Cmd =
let cmd: { key: String, value: Cmd } = cmd
io.print (" :" ++ cmd.key ++ " " ++ cmd.value.info)
) >>
return True
pure True
}
commands <- cmds
load commands
Expand All @@ -70,35 +71,35 @@ let do_command line: String -> IO Bool =
let arg = if string.length line >= 3 then string.trim (string.slice line 3 (string.length line)) else ""
match find cmd commands with
| Some command -> command.action arg
| None -> io.print ("Unknown command '" ++ cmd ++ "'") >> return True
| None -> io.print ("Unknown command '" ++ cmd ++ "'") >> pure True

let store line: String -> IO Bool =
let line = string.trim line
match string.find line " " with
| Some bind_end ->
let binding = string.slice line 0 bind_end
let expr = string.slice line bind_end (string.length line)
io.load_script binding expr >> return True
| None -> io.print "Expected binding in definition" >> return True
io.load_script binding expr >> pure True
| None -> io.print "Expected binding in definition" >> pure True

let loop editor: Editor -> IO () =
let run_line line =
if string.is_empty (string.trim line) then
return True
pure True
else if string.starts_with line ":" then
do_command line
else if string.starts_with line "def " then
store (string.slice line 4 (string.length line))
else
io.catch (io.run_expr line) return
io.catch (io.run_expr line) pure
>>= io.print
>> return True
>> pure True

rustyline.readline editor "> " >>= \line_opt ->
match line_opt with
| None -> return ()
| None -> pure ()
| Some line -> run_line line >>= \continue ->
if continue then loop editor else return ()
if continue then loop editor else pure ()

let run x: () -> IO () =
io.print "gluon (:h for help, :q to quit)"
Expand Down
2 changes: 1 addition & 1 deletion std/state.glu
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ let monad: Monad (State s) =
and m2 = f value
m2 state

{ (>>=), return = applicative.pure }
{ (>>=) }

let put value: s -> State s () = \state -> { value = (), state = value }

Expand Down
13 changes: 7 additions & 6 deletions std/test.glu
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ let string = import "std/string.glu"
and writer = import "std/writer.glu"
and { Writer, tell } = writer
and prelude = import "std/prelude.glu"
and { Show, Num, Eq, Option, List, Monad, Monoid, foldl } = prelude
and { Show, Num, Eq, Option, List, Applicative, Monad, Monoid, foldl } = prelude
and { (+) } = prelude.num_Int
and { (==) } = prelude.eq_Int
and { (<) } = prelude.make_Ord prelude.ord_Int
Expand All @@ -11,15 +11,16 @@ let (++) = string.monoid.(<>)

type Test a = Writer (List String) a

let monad: Monad Test = writer.make_Monad prelude.monoid_List
let applicative : Applicative Test = writer.make_Applicative prelude.monoid_List
let monad : Monad Test = writer.make_Monad prelude.monoid_List

let { (>>=), return, (>>), join, map = fmap, lift2, forM_ }
= prelude.make_Monad monad
let { pure } = applicative
let { (>>=), (>>), join, lift2, forM_ } = prelude.make_Monad monad applicative

let assert x = if x then () else error "Assertion failed"
and assert_eq show eq = \x y ->
if eq.(==) x y
then return ()
then pure ()
else tell (Cons ("Assertion failed: "
++ show.show x ++ " != " ++ show.show y) Nil)

Expand All @@ -32,4 +33,4 @@ let run test: Test a -> () =
| Cons _ _ -> error (prelude.foldl (\acc err -> acc ++ "\n" ++ err) "" test.writer)
| Nil -> ()

{ Test, monad, assert, assert_eq, assert_ieq, assert_feq, assert_seq, run }
{ Test, applicative, monad, assert, assert_eq, assert_ieq, assert_feq, assert_seq, run }
3 changes: 1 addition & 2 deletions std/writer.glu
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ let make_Applicative w: Monoid w -> Applicative (Writer w) =

let make_Monad w: Monoid w -> Monad (Writer w) =
let { (<>) } = w
let { pure } = make_Applicative w

let (>>=) m f : Writer w a -> (a -> Writer w b) -> Writer w b =
let { value, writer } = f m.value
{ value, writer = m.writer <> writer }

{ (>>=), return = pure }
{ (>>=) }

let tell w: w -> Writer w () =
{ value = (), writer = w }
Expand Down
5 changes: 3 additions & 2 deletions tests/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ fn read_file() {
let text = r#"
let prelude = import "std/prelude.glu"
let { assert } = import "std/test.glu"
let { (>>=), return } = prelude.monad_IO
let { pure } = prelude.applicative_IO
let { (>>=) } = prelude.monad_IO
io.open_file "Cargo.toml" >>= \file ->
io.read_file file 9 >>= \bytes ->
assert (array.length bytes == 9)
assert (array.index bytes 0 #Byte== 91b) // [
assert (array.index bytes 1 #Byte== 112b) // p
return (array.index bytes 8)
pure (array.index bytes 8)
"#;
let result = Compiler::new()
.run_io_expr::<u8>(&thread, "<top>", text);
Expand Down
7 changes: 3 additions & 4 deletions tests/pass/alternative.hs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
let { run, monad, assert_eq } = import "std/test.glu"
let { run, applicative, monad, assert_eq } = import "std/test.glu"
let prelude = import "std/prelude.glu"
let { Applicative } = prelude
let { (>>=), return, (>>), join, map, lift2, forM_ }
= prelude.make_Monad monad
let { (>>) } = prelude.make_Monad monad applicative

let test_alt show eq fun alt app =
let test_alt show eq fun alt app =
let { (<|>), empty, many, some } = prelude.make_Alternative fun app alt
let { (<*>), pure } = app
let assert =
Expand Down
5 changes: 2 additions & 3 deletions tests/pass/arithmetic.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
let { run, monad, assert, assert_ieq, assert_feq } = import "std/test.glu"
let { run, applicative, monad, assert, assert_ieq, assert_feq } = import "std/test.glu"
let prelude = import "std/prelude.glu"
let { Num } = prelude
let { (>>=), return, (>>), join, map = fmap, lift2, forM_ }
= prelude.make_Monad monad
let { (>>) } = prelude.make_Monad monad applicative

let int_tests =
let { (+), (-), (*) } = prelude.num_Int
Expand Down
5 changes: 2 additions & 3 deletions tests/pass/channel.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
let { run, monad, assert_eq } = import "std/test.glu"
let { run, applicative, monad, assert_eq } = import "std/test.glu"
let prelude = import "std/prelude.glu"
let { (>>=), return, (>>), join, map, lift2, forM_ }
= prelude.make_Monad monad
let { (>>) } = prelude.make_Monad monad applicative

let assert =
assert_eq (prelude.show_Result prelude.show_Unit prelude.show_Int )
Expand Down
8 changes: 4 additions & 4 deletions tests/pass/lazy.hs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
let { run, monad, assert_ieq } = import "std/test.glu"
let { run, applicative, monad, assert_ieq } = import "std/test.glu"
let prelude = import "std/prelude.glu"
let { Num } = prelude
let { (>>=), return, (>>), join, map, lift2, forM_ }
= prelude.make_Monad monad
let { pure } = applicative
let { (>>) } = prelude.make_Monad monad applicative
let { (+), (-), (*) } = prelude.num_Int

let l = lazy (\_ -> 123 + 57)

assert_ieq (force (lazy \_ -> 2)) 2 >>
return () >>
pure () >>
assert_ieq 180 (force l)
4 changes: 2 additions & 2 deletions tests/pass/map.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
let prelude = import "std/prelude.glu"
let { Monad, Monoid, Option, List, Eq, Show } = prelude
let string = import "std/string.glu"
let { Test, run, monad, assert, assert_eq } = import "std/test.glu"
let { Test, run, applicative, monad, assert, assert_eq } = import "std/test.glu"
let map = import "std/map.glu"
let { (>>) } = prelude.make_Monad monad
let { (>>) } = prelude.make_Monad monad applicative

let show_Entry e =
let { key, value } = e
Expand Down
5 changes: 1 addition & 4 deletions tests/pass/reference.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
let { run, monad, assert, assert_ieq, assert_feq } = import "std/test.glu"
let { assert } = import "std/test.glu"
let prelude = import "std/prelude.glu"
let { Num, Eq } = prelude
let { (==) } = prelude.eq_Int
let { (>>=), return, (>>), join, map = fmap, lift2, forM_ }
= prelude.make_Monad monad

let ri = ref 0
assert (0 == load ri)
Expand Down
8 changes: 4 additions & 4 deletions tests/pass/state.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
let prelude = import "std/prelude.glu"
let { Monad, Num } = prelude
let { Test, run, monad = monad_Test, assert, assert_ieq, assert_feq, assert_seq } = import "std/test.glu"
let { State, monad = monad_State, put, get, modify, runState, evalState, execState } = import "std/state.glu"
let { (>>) = (>>>) } = prelude.make_Monad monad_Test
let { (>>=), return, (>>) } = prelude.make_Monad monad_State
let { Test, run, applicative = applicative_Test, monad = monad_Test, assert, assert_ieq, assert_feq, assert_seq } = import "std/test.glu"
let { State, applicative = applicative_State, monad = monad_State, put, get, modify, runState, evalState, execState } = import "std/state.glu"
let { (>>) = (>>>) } = prelude.make_Monad monad_Test applicative_Test
let { (>>) } = prelude.make_Monad monad_State applicative_State
let { (+), (-), (*) } = prelude.num_Int

let tests =
Expand Down
7 changes: 3 additions & 4 deletions tests/pass/stream.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
let prelude = import "std/prelude.glu"
let { run, monad, assert_eq, assert_ieq } = import "std/test.glu"
let { run, applicative, monad, assert_eq, assert_ieq } = import "std/test.glu"
let stream = import "std/stream.glu"
let { Ord, Num, List, Option } = prelude
let { (<) } = prelude.make_Ord prelude.ord_Int
let { (+) } = prelude.num_Int
let { (>>=), return, (>>), join, map, lift2, forM_ }
= prelude.make_Monad monad
let { (>>) } = prelude.make_Monad monad applicative

let s = stream.from (\i -> if i < 5 then Some i else None)

let assert_leq = assert_eq (prelude.show_List prelude.show_Int) (prelude.eq_List prelude.eq_Int)

assert_ieq (stream.fold (+) 0 s) 10 >>
assert_ieq (stream.fold (+) 0 s) 10 >>
assert_leq (stream.fold (\h l -> Cons h l) Nil s) (Cons 4 (Cons 3 (Cons 2 (Cons 1 (Cons 0 Nil)))))
Loading

0 comments on commit e893f50

Please sign in to comment.