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.