Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscellaneous additions #1

Merged
merged 36 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f37adb6
instantiate monoid for unit
pxeger Aug 3, 2023
ca68f49
Control: cleanup and code deduplication
pxeger Aug 3, 2023
eca1304
fix List applicative implementation
pxeger Aug 3, 2023
e4d65dd
make definition of Monad_plus consistent
pxeger Aug 3, 2023
c9ff356
add list monoid
pxeger Aug 3, 2023
65e8ca8
add tests for string monoid
pxeger Aug 3, 2023
d5e8a8a
fix typo
pxeger Aug 3, 2023
cdb9a41
explicitly annotate that we expect List to satisfy Functor etc.
pxeger Aug 3, 2023
8d7a25b
improve Monad factory comment
pxeger Aug 3, 2023
134a261
add `with type 'a t = 'a M.t` to Monad
pxeger Aug 3, 2023
0ca7c07
improve with type annotation on List
pxeger Aug 3, 2023
7dfe6cf
fix traverse implementation
pxeger Aug 3, 2023
d55660a
add tests for list instances
pxeger Aug 3, 2023
b7b3b1f
clarify the meaning of unqualified "t" in Option
pxeger Aug 3, 2023
aeec009
Update lib/control.ml
pxeger Aug 3, 2023
33cb03d
Update lib/control.ml
pxeger Aug 3, 2023
5e7cbab
use List.fold_left
pxeger Aug 4, 2023
2e99ffe
fix type errors
pxeger Aug 4, 2023
ba63044
add tests for option instances
pxeger Aug 4, 2023
ef7d9f4
add signature for Option module
pxeger Aug 4, 2023
65931a0
split Option and List tests
pxeger Aug 4, 2023
e11a836
add functor etc. instances for functions and pairs
pxeger Aug 4, 2023
3deca46
add (commented-out due to bug) tests for sequence
pxeger Aug 4, 2023
a1419e8
rename Any.t to Any.t_for_any to avoid potential overlapping instances
pxeger Aug 4, 2023
cc7f909
add Any instance for lists
pxeger Aug 4, 2023
d84aec9
remove duplicate declaration of Num
pxeger Aug 4, 2023
3d4a012
remove duplicate Show classes
pxeger Aug 4, 2023
067a7b0
add show instances for more sizes of tuples
pxeger Aug 4, 2023
4abf10c
strengthen typing of Ord.compare
pxeger Aug 7, 2023
24e1050
remove ambiguous instantiations of Monoid for numeric types
pxeger Aug 7, 2023
ab21e06
add type signatures for instances of Eq, Num, Enum, etc.
pxeger Aug 7, 2023
3701b83
add const and identity functors
pxeger Aug 8, 2023
5d5b2ff
add myself as author
pxeger Aug 8, 2023
2b0dd8f
instantiate Applicative for Const of a Monoid
pxeger Aug 9, 2023
05a844b
change type of translateCompare
pxeger Aug 9, 2023
e3c744a
mark Functor et al as covariant
pxeger Aug 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion imp.opam
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: "imp"
synopsis: "Experimental library using modular implicits"
version: "dev"
maintainer: "yallop@gmail.com"
authors: ["Leo White" "Jeremy Yallop"]
authors: ["Leo White" "Jeremy Yallop" "Patrick Reader"]
homepage: "https://github.com/modular-implicits/imp"
dev-repo: "git+https://github.com/modular-implicits/imp.git"
bug-reports: "http://github.com/modular-implicits/imp/issues"
Expand Down
8 changes: 8 additions & 0 deletions lib/any.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module type Any = sig
type t_for_any
end

implicit module Any_Int = struct type t_for_any = int end
implicit module Any_String = struct type t_for_any = string end
implicit module Any_List {A : Any} = struct type t_for_any = A.t_for_any list end
implicit module Any_Pair {A : Any} {B : Any} = struct type t_for_any = A.t_for_any * B.t_for_any end
141 changes: 94 additions & 47 deletions lib/control.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
(* Funtor, Applicative and Monad module types *)
open Any

(* Functor, Applicative and Monad module types *)
module type Functor = sig
type 'a t
type +'a t
val fmap : ('a -> 'b) -> 'a t -> 'b t
end;;

Expand Down Expand Up @@ -44,12 +46,14 @@ let sequence {M : Monad} (ms : 'a M.t list) =
ms
(return [])

(* Create a monad using default functor and idiom implementation *)
(* Create a functor, applicative, and monad from just return and bind,
using default functor and applicative implementation *)
module Monad(M : sig
type 'a t
type +'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end) = struct
end): Monad with type 'a t = 'a M.t = struct
type +'a t = 'a M.t
(* Functor *)
let fmap f m = M.bind m (fun x -> M.return (f x))
(* Applicative *)
Expand All @@ -62,30 +66,9 @@ module Monad(M : sig
let bind = M.bind
end;;

(* Monad for option *)
implicit module MonadOption = Monad(struct
type 'a t = 'a option
let return x = Some x
let bind x f = match x with
| None -> None
| Some x -> f x
end);;

(* Monad for list *)
implicit module MonadList = Monad(struct
type 'a t = 'a list
let return x = [x]
let bind x f =
let rec aux acc = function
| x :: xs -> aux (x @ acc) xs
| [] -> acc
in
aux [] (List.rev_map f x)
end);;

module type Monad_plus = sig
include Monad
val mzero : unit -> 'a t
val mzero : 'a t
val mplus : 'a t -> 'a t -> 'a t
end

Expand All @@ -97,7 +80,7 @@ module Monad_plus = struct
if b then
M.return ()
else
M.mzero ()
M.mzero
end

module type Foldable = sig
Expand All @@ -119,7 +102,14 @@ module Traversable = struct
let traverse {T : Traversable} = T.traverse
end

implicit module Option = struct
implicit module Option: sig
include Functor with type 'a t = 'a option
include Applicative with type 'a t := 'a t
include Monad with type 'a t := 'a t
include Monad_plus with type 'a t := 'a t
include Foldable with type 'a t := 'a t
include Traversable with type 'a t := 'a t
end = struct
type 'a t = 'a option

(* Functor *)
Expand All @@ -128,13 +118,12 @@ implicit module Option = struct
| Some a -> Some (f a)

(* Applicative *)
let pure x = Some x
let return x = Some x
pxeger marked this conversation as resolved.
Show resolved Hide resolved
let apply f x = match f, x with
| Some f, Some x -> Some (f x)
| _, _ -> None

(* Monad *)
let return x = Some x
let bind x f = match x with
| None -> None
| Some x -> f x
Expand All @@ -150,40 +139,98 @@ implicit module Option = struct
| None -> acc
| Some x -> f x acc

let traverse (type a) (type b) {F : Applicative} (f : a -> b F.t) : a option -> b t F.t = function
(* Traversable *)
let traverse (type a) (type b) {F : Applicative} (f : a -> b F.t) : a option -> b option F.t = function
| None -> F.return None
| Some x -> F.fmap (fun x -> Some x) (f x)
end

implicit module List = struct
implicit module List : sig
pxeger marked this conversation as resolved.
Show resolved Hide resolved
include Functor with type 'a t = 'a list
include Applicative with type 'a t := 'a t
include Monad with type 'a t := 'a t
include Monad_plus with type 'a t := 'a t
include Foldable with type 'a t := 'a t
include Traversable with type 'a t := 'a t
end = struct
type 'a t = 'a list

(* Functor *)
let fmap = List.map

(* Monad *)
(* Applicative *)
let return x = [x]
let bind x f =
let rec aux acc = function
| x :: xs -> aux (x @ acc) xs
| [] -> acc in
aux [] (List.rev_map f x)
let apply fs xs =
List.concat (List.map (fun f -> List.map (fun x -> f x) xs) fs)

(* Applicative *)
let pure x = [x]
let apply fs xs = bind fs (bind xs)
(* Monad *)
let bind x f = List.concat (List.map f x)

(* Monad_plus *)
let mzero = []
let mplus = (@)

(* Foldable *)
let rec fold f t acc = match t with
| [] -> acc
| x :: xs -> fold f xs (f x acc)
let fold f xs a = List.fold_left (fun x y -> f y x) a xs

(* Traversable *)
let traverse {F : Applicative} f t =
let cons x ys = F.apply (F.apply (F.return (fun x xs -> x :: xs)) (f x)) ys in
fold cons t (F.return [])
let cons x ys = F.apply (F.fmap (fun x xs -> x :: xs) (f x)) ys in
List.fold_right cons t (F.return [])
end

implicit module Function {A : Any} : sig
include Functor with type 'b t = A.t_for_any -> 'b
include Applicative with type 'b t := 'b t
include Monad with type 'b t := 'b t
end = struct
type 'b t = A.t_for_any -> 'b

(* Functor *)
let fmap m f x = m (f x)

(* Applicative *)
let return x _ = x
let apply f g x = f x (g x)

(* Monad *)
let bind g f x = f (g x) x
end
(** (a -> b) is an instance of Monad b - it behaves like the reader monad *)

implicit module Pair {A : Any} : Functor with type 'b t = A.t_for_any * 'b = struct
type 'b t = A.t_for_any * 'b

let fmap m (a, b) = (a, m b)
end

type ('a, 'b) const = Const of 'a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether this can be defined simply as

Suggested change
type ('a, 'b) const = Const of 'a
type ('a, 'b) const = 'a

If it does need to be a proper (generative) type, it'd be better as a record, so that it's easy to destruct as well as construct:

type ('a, 'b) const = { const: 'a }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Daniel wants me to merge this so I'm going to make this an issue and deal with it later


implicit module Const {A : Any}: sig
include Functor with type 'b t = (A.t_for_any, 'b) const
end = struct
type 'b t = (A.t_for_any, 'b) const
let fmap _ (Const x) = (Const x)
end

implicit module Const_Applicative {A: Data.Monoid}: Applicative with type 'b t = (A.t, 'b) const
= struct
type 'b t = (A.t, 'b) const
let fmap _ (Const x) = (Const x)
let return _ = Const (Data.Monoid.empty ())
let apply (Const a) (Const a') = Const (Data.Monoid.append a a')
end

type 'b identity = Identity of 'b

implicit module Identity: sig
include Functor with type 'b t = 'b identity
include Applicative with type 'b t := 'b t
include Monad with type 'b t := 'b t
end = struct
type 'b t = 'b identity
let fmap f (Identity b) = Identity (f b)
let return b = Identity b
let apply (Identity f) (Identity x) = Identity (f x)
let bind (Identity x) f = f x
end
Loading