···11+; (executables
22+; (names main task)
33+; (libraries base eio_posix shelter.main))
+129
attic/main.ml
···11+module type Applicative = sig
22+ type 'a t
33+44+ val return : 'a -> 'a t
55+ val fmap : ('a -> 'b) -> 'a t -> 'b t
66+ val mbind : ('a -> 'b t) -> 'a t -> 'b t
77+ val apply : ('a -> 'b) t -> 'a t -> 'b t
88+end
99+1010+module type Selective = sig
1111+ include Applicative
1212+1313+ val select : ('a, 'b) Either.t t -> ('a -> 'b) t -> 'b t
1414+end
1515+1616+1717+module T (A : Applicative) = struct
1818+1919+ let do_thing (a : _ A.t) (v : _ A.t) =
2020+ let v1 = A.mbind (fun i -> if Random.int i < 5 then A.mbind (fun v -> A.return @@ v ^ "hello") v else A.return "world") a in
2121+ let v2 = A.fmap (fun i -> if Random.int i < 5 then "hello" else "world") a in
2222+ v1, v2
2323+end
2424+2525+module Make (S : Selective) = struct
2626+ include S
2727+2828+ let ( <*? ) x f = S.select x f
2929+ let map ~f x = apply (return f) x
3030+3131+ let branch x l r =
3232+ map x ~f:(Either.map ~left:Fun.id ~right:Either.left)
3333+ <*? map l ~f:(Fun.compose Either.right)
3434+ <*? r
3535+3636+ let if' x t f =
3737+ branch
3838+ (map x ~f:(fun b -> if b then Either.Left () else Either.Right ()))
3939+ (map t ~f:Fun.const) (map f ~f:Fun.const)
4040+4141+ let when' x act = if' x act (return ())
4242+ let ( <||> ) a b = if' a (return true) b
4343+ let ( <&&> ) a b = if' a b (return false)
4444+end
4545+4646+module Shl (S : Selective) = struct
4747+ module Select = struct
4848+ include Make (S)
4949+ end
5050+5151+ module Shelter = Shelter_main
5252+5353+ type step =
5454+ | From : string -> step
5555+ | Run : string -> step
5656+ | Copy : string * string -> step
5757+ | Parallel : string list -> step
5858+5959+ type 'a with_session = { session : string; step : 'a }
6060+ type 'a llist = Singleton of 'a | Cons of 'a * 'a llist
6161+6262+ let rec map f = function
6363+ | Singleton v -> Singleton (f v)
6464+ | Cons (x, xs) -> Cons (f x, map f xs)
6565+6666+ type t = step with_session llist
6767+6868+ let from image =
6969+ Select.return (Singleton { session = "main"; step = From image })
7070+7171+ let run cmd =
7272+ Select.return (function (Singleton prev | Cons (prev, _)) as l ->
7373+ Cons ({ prev with step = Run cmd }, l))
7474+7575+ let copy ~src ~dst = Select.return (Copy (src, dst))
7676+7777+ let session session =
7878+ Select.return (function (Singleton step | Cons (step, _)) as l ->
7979+ Cons ({ step with session }, l))
8080+8181+ let with_session session = Select.return (map (fun v -> { v with session }))
8282+8383+ let rec to_list = function
8484+ | Singleton v -> [ v ]
8585+ | Cons (x, xs) -> x :: to_list xs
8686+8787+ let stdout _ = ""
8888+8989+ let build steps =
9090+ Select.apply
9191+ (Select.return (fun steps ->
9292+ to_list steps |> List.rev
9393+ |> List.map (function
9494+ | { session; step = From from } ->
9595+ Printf.sprintf "(%s) FROM %s" session from
9696+ | { session; step = Run cmd } ->
9797+ Printf.sprintf "(%s) RUN %s" session cmd
9898+ | { session; step = Copy (src, dst) } ->
9999+ Printf.sprintf "(%s) COPY %s %s" session src dst
100100+ | _ -> assert false)
101101+ |> String.concat "\n"))
102102+ steps
103103+end
104104+105105+module Identity = Make (struct
106106+ type 'a t = 'a
107107+108108+ let return x = x
109109+ let apply f x = f x
110110+ let select e f = match e with Either.Left v -> f v | Either.Right b -> b
111111+end)
112112+113113+module D = Shl (Identity)
114114+115115+let dockerfile =
116116+ let open D in
117117+ let base_image = from "alpine" in
118118+ let is_node_lst img = String.equal "v22.15.0" (stdout img) in
119119+ let cmds base =
120120+ let node_version = run "node --version" base in
121121+ Select.if'
122122+ (Select.map ~f:is_node_lst node_version)
123123+ (run "node -e 'console.log('success!')")
124124+ (run "node -e 'console.log('failure!')")
125125+ base
126126+ in
127127+ with_session "node" (cmds base_image)
128128+129129+let () = print_endline (D.build dockerfile)
+106
attic/task.ml
···11+(* Work in progress, prototyped in https://try.ocamlpro.com/. To be modified
22+ for Base. *)
33+44+module type Applicative = sig
55+ type 'a t
66+77+ val return : 'a -> 'a t
88+ val apply : ('a -> 'b) t -> 'a t -> 'b t
99+end
1010+1111+module type Selective = sig
1212+ include Applicative
1313+1414+ val select : ('a, 'b) Either.t t -> ('a -> 'b) t -> 'b t
1515+end
1616+1717+module Make (S : Selective) = struct
1818+ include S
1919+2020+ let ( <*? ) x f = S.select x f
2121+ let map ~f x = apply (return f) x
2222+2323+ let branch x l r =
2424+ map x ~f:(Either.map ~left:Fun.id ~right:Either.left)
2525+ <*? map l ~f:(Fun.compose Either.right)
2626+ <*? r
2727+2828+ let if' x t f =
2929+ branch
3030+ (map x ~f:(fun b -> if b then Either.Left () else Either.Right ()))
3131+ (map t ~f:Fun.const) (map f ~f:Fun.const)
3232+3333+ let when' x act = if' x act (return ())
3434+ let ( <||> ) a b = if' a (return true) b
3535+ let ( <&&> ) a b = if' a b (return false)
3636+end
3737+3838+module type Task = sig
3939+ type k
4040+ type v
4141+4242+ val exec : k -> v
4343+4444+ module Make (S : Selective) : sig
4545+ val run : (k -> v S.t) -> v S.t
4646+ end
4747+end
4848+4949+module Example : Task with type k = string and type v = int = struct
5050+ type k = string
5151+ type v = int
5252+5353+ let exec s = Sys.command s
5454+5555+ module Make (Select : Selective) = struct
5656+ module S = Make (Select)
5757+5858+ let run exec =
5959+ S.if'
6060+ (S.map (exec "node") ~f:(fun x -> x = 0))
6161+ (exec "echo 'node!'") (exec "echo 'no node'")
6262+ end
6363+end
6464+6565+module Dependencies (Task : Task) : sig
6666+ val deps : Task.k list
6767+ val v : Task.v
6868+end = struct
6969+ module Ks = Make (struct
7070+ type 'a t = Task.k List.t
7171+7272+ let return _ = []
7373+ let apply x y = List.append x y
7474+ let map = `Define_using_apply
7575+ let select x y = List.append x y
7676+ end)
7777+7878+ module Xs : Selective with type 'a t = 'a = struct
7979+ type 'a t = 'a
8080+8181+ let return v = v
8282+ let apply f y = f y
8383+ let map = `Define_using_apply
8484+8585+ let select either f =
8686+ match either with
8787+ | Either.Left v ->
8888+ Format.printf "Either left\n%!";
8989+ f v
9090+ | Either.Right b ->
9191+ Format.printf "Either right\n%!";
9292+ b
9393+ end
9494+9595+ module Ys = Make (Xs)
9696+ module M = Task.Make (Ks)
9797+ module T = Task.Make (Ys)
9898+9999+ let deps = M.run (fun v -> [ v ])
100100+ let v = T.run Task.exec
101101+end
102102+103103+let () =
104104+ let module D = Dependencies (Example) in
105105+ (* List.iter (Format.printf "Dep: %s\n%!") D.deps; *)
106106+ Format.printf "Result: %i\n" D.v