Haskell has a function `fmap`

which can map over a number of different datatypes. For example, `fmap`

can map a function over both a `List`

and a `Maybe`

(the equivalent of an `option`

in OCaml):

```
Prelude> fmap (+ 1) [1,2]
[2,3]
Prelude> fmap (+ 1) (Just 3)
Just 4
```

Unfortunately, the equivalent is impossible in OCaml. That is, there's no way to define an OCaml value `fmap`

so that the two expressions:

```
# fmap [1;2] ~f:((+) 1)
# fmap (Some 3) ~f:((+) 1)
```

both typecheck and evaluate to the right value.

Even if we eliminate the complexity of type inference by specifying the type explicitly, we can't define `fmap`

so that the two expressions:

```
# fmap ([1;2] : _ list) ~f:((+) 1)
# fmap (Some 3 : _ option) ~f:((+) 1)
```

typecheck and evaluate to the right value.

However, the `Generic`

module in Jane Street's `Core_extended`

library will let us do exactly that with just a trivial syntactic change. But before continuing, I'll warn you that the `Generic`

module is not necessarily something you'd want to use in real world code; it falls much more in the "cute trick" category. But with that caveat, let's look at our example using `Generic`

:

```
# open Core.Std;;
# open Core_extended.Generic;;
# map ([1;2] >: __ list) ~f:((+) 1);;
- : int list = [2; 3]
# map (Some 3 >: __ option) ~f:((+) 1);;
- : int option = Some 4
```

Note that, after opening the `Generic`

module, all we did to the previous example was change `:`

to `>:`

and `_`

to `__`

. (Also, the `Generic`

module calls the mapping function `map`

instead of `fmap`

, but that's inconsequential.)

Of course, the trick is that `>:`

, `__`

, `list`

, and `option`

are actually values defined by the `Generic`

module in such a way that their intended usage looks like a type annotation.

Note that these "types" are nestable as you would expect real types to be:

```
# map ([None; Some 3] >: __ option list) ~f:((+) 1);;
- : int option list = [None; Some 4]
```

This means that you can change what map does just by changing the "type" you assign to its argument:

```
# map ([None; Some 3] >: __ option list) ~f:(fun _ -> ());;
- : unit option list = [None; Some ()]
# map ([None; Some 3] >: __ list) ~f:(fun _ -> ());;
- : unit list = [(); ()]
```

The `Generic`

module also defines a generic `fold`

function so that you can accumulate values at any "depth" in your value:

```
# fold ([[Some 3; None]; [Some 5; Some 2]] >: __ option list list) ~init:0 ~f:(+);;
- : int = 10
```

Not every "type" formable is `__`

followed by some sequence of `option`

s and `list`

s: for example, `Generic`

also provides `string`

(considered as a container of characters):

```
# map ([Some "foo"; None; Some "bar"] >: string option list) ~f:Char.uppercase;;
- : string option list = [Some "FOO"; None; Some "BAR"]
```

Note that the fact that the "types" are nestable means that these values must have unusual definitions: in particular, `__`

(and `string`

) are functions which must be able to take a variable number of arguments. Indeed, these values are defined using a technique sweeks wrote about in a blog post on variable argument functions: the `f`

and `z`

in sweeks's post are analogous here to `__`

and `>:`

respectively.

Here's the definition of the primitive values we've used so far (`Generic`

actually defines a few more):

```
let __ k = k (fun f x -> f x)
let ( >: ) x t y = t (fun x -> x) y x
let map x ~f = x f
let string k = k (fun f -> String.map ~f)
let list map k = k (fun f -> List.map ~f:(map f))
let option map k = k (fun f -> Option.map ~f:(map f))
```

The types of these turn out to be extremely unhelpful, and you can't really use them to figure out how to use these values. For example, here is the type of `>:`

(and this isn't just the inferred type of the above definition, this is the type which must actually be exposed to use `>:`

):

```
val ( >: ) : 'a -> (('b -> 'b) -> 'c -> 'a -> 'd) -> 'c -> 'd
```

Finally, is this module actually used? The answer is no. As far as I know, it's used nowhere in Jane Street's codebase. But it's still kind of cute.