Isn't that lisptype still missing the fundamental characteristic of accepting *any* type? What of user-defined types?
If you have to jump through hoops to create even a semi-generic type, wouldn't you just start going about solving the problem in such a way that generics aren't required? It'd be like programming in *shudder* java.
Well, in this case I don't want it to accept *any* type... just a lisptype.
By default, OCaml lists accept any type. You just cannot mix types. But you can create lists of ints, floats, strings, lisptypes, etc, without any hassle.
All the stuff in the blog post was necessary (or so I think :-) to create my own type, lisptype, which was complicated by the mutually recursive definitions. (lisptype can be a lisplist, among other things, but lisplists consist of lisptypes...)
Note that the lisptype is really a way to tell OCaml that multiple types are allowed... lisptype can map to an int, a float, a rational (tuple of two ints), a lisplist, etc. We cannot have a list like Python or Lisp, that accept mixed types... so we have to work around it with a user-defined type. This to keep the type checker happy. (And we want that so we can reap the benefits from it, like type inference, pattern matching etc.)
I'll post a note demonstrating how to use the new type, by the way.
"""[...] so we have to work around it with a user-defined type. This to keep the type checker happy."""
Actually, this make it sounds like it's just a hack, a workaround. That is not the case; this is simply how you do these things in a language as strongly typed as this.
OCaml will still not allow us to have lists of mixed types... that would throw the whole type system out the door. But what we *can* do is define our own type, as an umbrella for the things we want, and use that. So, in defining lisptype, we just use the types we need, and those will be allowed in a lisplist... other types won't. Makes sense, IMHO.
"You cannot mix types..."
# let cons a b = a,b;;
val cons : 'a -> 'b -> 'a * 'b =
# cons 42 (cons 3.14159 (cons "String" ()));;
- : int * (float * (string * unit)) = (42, (3.14159, ("String", ())))
Hm, yes, but I meant that the OCaml list type doesn't allow you to mix types. As you demonstrate here, you can of course build your own list structure using tuples. But I'm not sure... isn't that a dead end? How are you going to do anything with such a list, like, for example, iterating over it and printing each element?
Well, if you want to iterate over such a self-made list, you'd need a function that is absolutely generic (Pity OCaml does not sport a truly generic "print" function). You could however create one outside of the language.
On the other hand, if you have a list with different types, the last thing you usually want to do is to iterate over it - at least in OCaml, which has tuples or records or even objects for this kind of stuff.
For writing a lisp interpreter, your lispType scheme (no pun intended) is preferrable, and even Genlex uses something like it. You retain type safety and can stay in OCaml.