Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursive instances? #32

Open
yallop opened this issue Mar 23, 2015 · 3 comments
Open

Recursive instances? #32

yallop opened this issue Mar 23, 2015 · 3 comments

Comments

@yallop
Copy link
Contributor

yallop commented Mar 23, 2015

I'd like to write something analogous to the following Haskell code

{-# LANGUAGE RankNTypes #-}

class C a where
  f :: (forall b.C b => b -> b) -> a -> a

instance C a => C [a] where
  f g [] = []
  f g (x:xs) = g x : g xs

but I don't see how to make recursive instance resolution work. I suppose it should look something like this

module rec R:
sig
  module type C =
  sig
     type a
     val f : ((implicit B:R.C) -> B.a -> B.a) -> a -> a
  end
end = R
include R

implicit functor C_list(A:C) =
struct
  type a = A.a list
  let f (g : ((implicit B:C) -> B.a -> B.a)) = function
    [] -> []
  | x :: xs -> g x :: g xs
end

but that code doesn't work, of course, because C_list is not visible in the call g xs.

Is there some way to bring the implicit C_list instance into scope within its own body?

@yallop yallop changed the title Recursive instances Recursive instances? Mar 23, 2015
@yallop
Copy link
Contributor Author

yallop commented Mar 24, 2015

The workaround for this case is to use a non-recursive functor with a recursive module as the body:

implicit functor C_list(A:C) : C with type a = A.a list =
struct
  module rec S : C with type a = A.a list =
  struct
    type a = A.a list
    let f (g : ((implicit B:C) -> B.a -> B.a)) = 
      function
        [] -> []
      | x :: xs -> g (implicit A) x :: g (implicit S) xs
  end
  include S
end

@yallop
Copy link
Contributor Author

yallop commented Mar 24, 2015

A slightly lighter version, without explicitly-instantiated implicit arguments:

type f_arg = (implicit B:C) -> B.a -> B.a

implicit functor C_list(A:C) : C with type a = A.a list = struct
  module rec S : C with type a = A.a list = struct
    implicit module T = S
    type a = A.a list
    let f (g : f_arg) : a -> a = function
        [] -> []
      | x :: xs -> g x :: g xs
  end
  include S
end

@lpw25
Copy link
Member

lpw25 commented Mar 24, 2015

This is an interesting case. I hadn't really considered wanting to recursively use an instance within itself.

It seems that recursive functors should provide support for this, but recursive functors are very restricted in how they can be used -- you basically can't call them from within themselves. They are also not well specified. If recursive functors were improved/fixed then I think this example would just work naturally.

So I think that this example provides a use case and some motivation for fixing recursive functors, but that we shouldn't worry about it too much as part of the implicits work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants