# Which is less generic than

**URL:** <https://discuss.ocaml.org/t/which-is-less-generic-than/16987>\
**Category:** Learning\
**Tags:** type-system\
**Created:** [July 18, 2025, 8:20am UTC](https://discuss.ocaml.org/t/which-is-less-generic-than/16987 "2025-07-18T08:20:12Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [July 18, 2025, 8:20am UTC](https://discuss.ocaml.org/t/which-is-less-generic-than/16987/1 "2025-07-18T08:20:12Z")

</div>

Hello! I’m trying to get the types work for a `task` interface where a `task` is a function. But a `task` can depend on the output of other tasks so I want to pass in a `fetch` function. But tasks can return different types of values, so I’m trying to pass in a fetch function that is polymorphic but running into a type error. Below is the code I’m trying to implement, any ideas?

```ocaml
module K : sig
  type 'a t

  val int : string -> int t
  val to_string : 'a t -> string
end = struct
  type 'a t = string

  let int s = s
  let to_string t = t
end

type 'v task = { run : 'r. ('r K.t -> 'r) -> 'v }

let task = { run = (fun fetch -> fetch (K.int "foo")) }

```

Error:

```auto
69 | let task = { run = (fun fetch -> fetch (K.int "foo")) }
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This field value has type (int K.t -> int) -> int
       which is less general than 'r. ('r K.t -> 'r) -> 'a

```

---

<div class="post-metadata">

**Author:** ![yallop](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yallop/32/517_2.png) [@yallop](https://discuss.ocaml.org/u/yallop)\
**Post date:** [July 18, 2025, 8:37am UTC](https://discuss.ocaml.org/t/which-is-less-generic-than/16987/2 "2025-07-18T08:37:49Z")

</div>

> [@orbitz](#):
>
> ```auto
> type 'v task = { run : 'r. ('r K.t -> 'r) -> 'v }
> 
> ```

Your type has the quantifier scoping over the return type, ∀r.((r K.t → r) → v), which means that the _type of `run`_ is polymorphic.

But you want only the _type of `run`’s argument_ to be polymorphic, (∀r.(r K.t → r)) → v, which you can achieve with a record for the argument, as follows:

```auto
type fetcher = { fetch : 'r. 'r K.t -> 'r }
type 'v task = { run : fetcher -> 'v }
let task = { run = fun {fetch} -> fetch (K.int "foo")}

```

or, more simply:

```auto
type fetcher = { fetch : 'r. 'r K.t -> 'r }
let task {fetch} = fetch (K.int "foo")

```

---

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [July 18, 2025, 9:04am UTC](https://discuss.ocaml.org/t/which-is-less-generic-than/16987/3 "2025-07-18T09:04:18Z")

</div>

AHHH of course, so obvious. Thank you so much for the helpful and fast response!

---

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [July 18, 2025, 9:46am UTC](https://discuss.ocaml.org/t/which-is-less-generic-than/16987/4 "2025-07-18T09:46:12Z")

</div>

I have a follow up question: Given the answer above, is it possible to implement the following function?

```ocaml

  module Tasks = struct
    type t = { get : 'v. M.State.t -> 'v M.k -> 'v Task.t option M.C.t }
  end

```

The idea is to have some store of tasks which can all be heterogeneous in type and get one, if it exists. I am pretty sure I know how I can implement this with GADTs, but is it possible to have an implementation that is as naive as a `function`? Like the following:

```ocaml
let tasks =
  {
    get =
      (function
      | a -> Some { run = (fun _ -> 10) }
      | b -> Some { run = (fun _ -> "hi") }
      | _ -> None);
  }

```
