Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml - Unbound record field

I am new to OCaml and I am trying to convert some Haskell code to OCaml.

I have the following code, where I explore the OCaml module system and functors.

module type F =
  sig 
    type 'a f
    val fmap : ('a -> 'b) -> 'a f -> 'b f
  end

module type FOO =
  functor (C : F) ->
    sig
      type f 
    end

module Foo : FOO =
  functor (C : F) -> 
    struct
      type f = { foo : 'x . 'x C.f -> 'x ;
                 bar : 'x . 'x C.f -> 'x C.f }
    end

module List = 
  struct
    include List
    type 'a f = 'a list
    let fmap = List.map
  end

module Bar =
  struct
    include Foo (List)
    let ea = { foo = List.hd ; bar = List.tl }
  end

I keep having the error Unbound record field foo. The fact that Foo is a functor complicates matters, I feel like I cannot provide an annotation as I want to. What am I missing?

like image 977
Bird Avatar asked Nov 16 '25 09:11

Bird


1 Answers

The problem arises because you're saying that Foo has the signature of FOO, and in FOO you're saying that f is abstract, i.e. that its definition is hidden. From the compiler's perspective you've deliberately hidden the implementation details of Foo.f.

There are several way you can fix this:

  1. Remove the signature FOO from Foo, allowing it to be inferred instead.
module Foo =
  functor (C : F) -> 
    struct
      type f = { foo : 'x . 'x C.f -> 'x ;
                 bar : 'x . 'x C.f -> 'x C.f }
    end

will infer its type as

module Foo :
  functor (C : F) ->
    sig type f = { foo : 'x. 'x C.f -> 'x; bar : 'x. 'x C.f -> 'x C.f; } end
  1. Provide the full type definition of f in FOO.
module type FOO =
  functor (C : F) ->
    sig
      type f = { foo : 'x . 'x C.f -> 'x ;
                 bar : 'x . 'x C.f -> 'x C.f }
    end
  1. Add a constructor function to Foo and FOO that allow you to create values of type f without needing to know the exact details of its implementation. In this case this is however made more difficult by OCaml's lack of higher rank polymorphism, meaning you can't pass the universally quantified foo and bar functions to the constructor function directly (see Section 5.3 in the OCaml manual). The workaround is to wrap these functions in a record (or object), which effectively just brings us back to solution 2.
like image 111
glennsl Avatar answered Nov 19 '25 06:11

glennsl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!