0

This exercise I made up is intended to help me understand signatures, structures, and functors in Standard ML. I can't seem to get it to work. Just for reference, I'm using

Standard ML of New Jersey v110.75 [built: Sun Jan 20 21:55:21 2013]

I have the following ML signature for an "object for which you can compute magnitude":

signature MAG_OBJ =
sig
   type object
   val mag : object -> int
end

If I want to give a structure of "int sets with magnitude," I might have a structure for an ordered int to use with the standard library's ORD_SET signature as follows:

structure OrderedInt : ORD_KEY =
struct
   type ord_key = int
   val compare = Int.compare
end

Then I can create a functor to give me a structure with the desired types and properties:

functor MakeMagSet(structure ELT : ORD_KEY) : MAG_OBJ =
struct
   structure Set : ORD_SET = RedBlackSetFn(ELT)
   type object = Set.set
   val mag = Set.numItems
end

So far so good (everything compiles, at least). Now I create an instance of the structure for my OrderedInt structure I made above:

structure IntMagSet = MakeMagSet(structure ELT = OrderedInt)

But when I try to use it (create a set and compute its magnitude), I get an error:

val X = IntMagSet.Set.addList(IntMagSet.Set.empty, [0,1,2,3,4,5,6,7,8,9])

gives the error:

Error: unbound structure: Set in path IntMagSet.Set.empty.addList

From what I understand, ascribing a signature opaquely using :> makes it so one can't access any structure internals which are not defined explicitly in the signature, but I ascribed MAG_OBJ transparently, so I should be able to access the Set structure, right? What am I missing here?

[EDIT]

Even rewriting the functor to specifically bind the functions I want to the struct is no good:

functor MakeMagSet(structure ELT: ORD_KEY) : MAG_OBJ =
struct
   structure Set : ORD_SET = RedBlackSetFn(ELT)
   type object = Set.set
   val mag = Set.numItems
   val empty = Set.empty
   val addList = Set.addList
end

Trying to access "empty" and "addList" give unbound variable errors.

On the other hand, trying to explicitly define the Set structure outside of the struct and use its functions gives a type error upon calling mag:

Error: operator and operand don't agree [tycon mismatch]
  operator domain: IntMagSet.object
  operand:         Set.set
  in expression:
    IntMagSet.mag X
JeremyKun
  • 2,987
  • 2
  • 24
  • 44
  • Just realized I can't say "IntMagSet.Set.empty.addList", because I'm silly and got too used to object oriented style. I think there's still a problem here, but I have to edit the question. – JeremyKun Apr 29 '13 at 00:24

1 Answers1

1

I think it's because you explicitly said that the type of MakeMagSet makes a MAG_OBJ, whose signature does not contain Set. If you had gotten rid of the : MAG_OBJ or made MAG_OBJ include ORD_SET, then it will work.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • It doesn't make sense to have every MAG_OBJ include an ORD_SET, because what if I want to "compute magnitudes" on things that aren't sets? – JeremyKun Apr 29 '13 at 02:25
  • It seems that putting : MAG_OBJ does not simply verify that the resulting structure complies with an interface, but restricts it to do so. Removing : MAG_OBJ does indeed fix the problem. Now if I use it in, e.g. another functor, I can still put : MAG_OBJ and have it use the mag function, but then I can't refer to the underlying set anymore. This makes me wonder why type ascription in a functor is even a feature; it renders my structure completely useless! – JeremyKun Apr 29 '13 at 13:46