# Notes from Compose 2017

**URL:** <https://discuss.ocaml.org/t/notes-from-compose-2017/240>\
**Category:** Community\
**Tags:** event, bucklescript\
**Created:** [May 21, 2017, 5:54pm UTC](https://discuss.ocaml.org/t/notes-from-compose-2017/240 "2017-05-21T17:54:03Z")\
**Posts on this page:** 1\
**Showing post:** 6

<div class="post-metadata">

**Author:** ![gasche](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/gasche/32/4_2.png) [@gasche](https://discuss.ocaml.org/u/gasche)\
**Post date:** [May 26, 2017, 1:36am UTC](https://discuss.ocaml.org/t/notes-from-compose-2017/240/6 "2017-05-26T01:36:52Z")

</div>

I just looked at the slides on [Working with Monads in OCaml](https://bazaar.launchpad.net/~scompall/working-with-monads-in-ocaml/trunk/files). Slide 15/17 mentions that “you can’t pass functors to functors”, and that this is an issue to implement

```
traverse :: Applicative f => (a -> f b) -> t a -> t (f b)

```

Would anyone know what exactly was being meant? Because you can in fact take functors are arguments to functors, and you can do `traverse` this way:

```ocaml
module type Functor = sig
  type 'a t
  val map : ('a -> 'b) -> 'a t -> 'b t
end

module type Applicative = sig
  type 'a t
  include Functor with type 'a t := 'a t
  val pure : 'a -> 'a t
  val app : ('a -> 'b) t -> 'a t -> 'b t
end

module type Monad = sig
  type 'a t
  include Functor with type 'a t := 'a t
  val return : 'a -> 'a t
  val bind : 'a t -> ('a -> 'b t) -> 'b t
end

module type Traversal = sig
  type 'a t
  module Traverse : functor (F : Applicative) -> sig
    val traverse : ('a -> 'b F.t) -> 'a t -> 'b t F.t
  end
end

module List = struct
  type 'a t = 'a list
  let map = List.map
  let pure x = [x]
  let rec app fs xs = match fs, xs with
    | [], [] -> []
    | f::fs, x::xs ->
      let y = f x in y :: app fs xs
    | (_::_), [] | [], (_::_) -> invalid_arg "List.app"
  let return = pure
  let join = List.flatten 
  let bind m f = List.map f m |> join
  module Traverse (F : Applicative) = struct
    let rec traverse f = function
      | [] -> F.pure []
      | x::xs ->
        let y = f x in
        let ys = traverse f xs in
        let ($) = F.app in
        F.pure (fun y ys -> y::ys) $ y $ ys
  end
end

module Option = struct
  type 'a t = 'a option

  let map f = function
    | None -> None
    | Some x -> Some (f x)

  let pure x = Some x
  let app f m = match f, m with
    | Some f, Some x -> Some (f x)
    | None, _ | _, None -> None

  let return = pure
  let bind m f = match m with
    | None -> None
    | Some x -> f x
end

let () =
  let module T = List.Traverse(Option) in
  let open T in
  assert
    (traverse (function true -> Some 1 | false -> Some 2) [true; false; true]
     = Some [1; 2; 1]);
  assert
    (traverse (function true -> Some 1 | false -> None) [true; false; true]
     = None);
  ()

```

---

_[View the full topic](https://discuss.ocaml.org/t/notes-from-compose-2017/240)._
