Hacker News new | comments | show | ask | jobs | submit login
Irken Language – A Scheme with parametric polymorphism (nightmare.com)
106 points by wirrbel on Aug 5, 2014 | hide | past | web | favorite | 24 comments



Is it really Scheme if it's statically typed? I could see type hints or the like, but

> Expressions like '(1 "two" three) will not pass the type checker. All lists must be monomorphic, i.e., a list of ints, or a list of bools, etc...

seems to me to be such a big change as to mean it's not Scheme.

Don't get me wrong, I love the idea of statically-typed Scheme, and will look carefully at it. I just think it's odd to claim it's Scheme.


In a way, it really seems more like a dialect of ML with Scheme-like syntax. It's not just the monomorphic lists, it's also the algebraic data types and pattern matching.


If you want a typed Scheme that you can still write the way you write Scheme, take a look at Typed Racket.


I may look at it again. The last time I did so, the documentation was a bit uneven, which is something I've found to be true about Racket more generally (particularly the extensions).


If (1 "two" three) doesn't type check, then how do macros work? There must be an exception for the syntax itself. You should be able to write a macro (my-quote (1 "two" three)).


I wonder if something like this would be possible:

    (list (:myint 1) (:mystring "two") (:mysymbol 'three))

?


One thing I remain unclear about after reading this introduction... How do you reconcile monomorphic lists with function invocation while maintaining homoiconicity? Your use of the terminology here confuses me because elsewhere you claim the first value in a list is of a generic type; but the CDR of any list is also a list. Ergo the CAR of some lists CDR must be generic to maintain consistency. But here's the rub: that means you support polymorphic lists, so clearly I must be misunderstanding you.


The type of both the car and cdr is the generic 'a, but that's the same 'a, so the elements of a list are only of one type.


Nice that they have both (row) polymorphic records and polymorphic variants... but weird that you only implicitly state the variables in data declarations---it outlaws phantoms!


There is a lisp like syntax for ocaml provided by camlp4: http://docs.camlcity.org/docs/godisrc/camlp5-6.07.tgz/camlp5...


It's an impressive piece of work as for a Scheme implementation (saying this as a Scheme implementer myself[1]). I'd love to introduce some ML and static typing in my Scheme too.

I spent some time looking for the source code, then found it at the site one directory up: http://nightmare.com/rushing/irken/irken/ , just in case anyone's interested. It looks like the author does not use version control and Github at all.

[1] https://github.com/EarlGray/SECD


It's not very easy to find from the provided link, but there is a repo on GitHub: https://github.com/samrushing/irken-compiler


Scheme supports parametric polymorphism. This language adds only a type system, which supports parametric types needed to describe polymorphic code.

(Parametric polymorphism is a property of code, not of types. Specifically it is the ability for code to operate on data without knowing its ground type. The types which describe such things are called parametric types.)

Aside, I've noticed a few other articles which seem to imply that type systems bring capability. Type systems never add capability to an untyped language; they always restrict capability.† That is what makes types useful!

† Barring type-based dispatch, which is only dependent on type names; and run-time type introspection, which is wholly misguided.


Parametric polymorphism (i.e., generics) is a feature you find in statically typed languages, not dynamic languages like Scheme.

For example, Scheme doesn't let you do a version of (lambda (a b) (+ a b)) that somehow ensures at compile time that a and a are the same type, or even if the + operation is defined for all possible arguments you could pass into a and b. If you want to make any restrictions on the types of arguments being passed in, you need to handle that by checking the arguments' types at run-time. Whereas with generics, you would have to have a type argument attached to each of the parameters. At compile time, those type arguments are evaluated and everything still has to successfully pass a static type check.


somehow ensures at compile time that a and a are the same type

No, that's a feature of parameterized types. Here's a function that utilizes the parametric polymorphism present in Scheme:

    (lambda (f x) (f x))
Other examples include the built-in functions car, cdr, and cons. None of these functions are permitted in a language which does not support parametric polymorphism, such as C.


Parameterized types are a part of parametric polymorphism.

Scheme does allow a function like (lambda (f x) (f x)), but that's because it's dynamically typed. It can just compile a single version of the lambda that is capable of handling all possible input types - no polymorphism required, parametric or otherwise.

Whereas in a language like ML with static typing the compiler would need to compile different polymorphic versions of the function for all the different combinations of types for f and x that are being used in the program.


> It can just compile a single version of the lambda that is capable of handling all possible input types - no polymorphism required, parametric or otherwise.

That's the very definition of parametric polymorphism. From http://en.wikipedia.org/wiki/Polymorphism_(computer_science): If the code is written without mention of any specific type and thus can be used transparently with any number of new types, it is called parametric polymorphism.

> Whereas in a language like ML with static typing the compiler would need to compile different polymorphic versions of the function for all the different combinations of types for f and x that are being used in the program.

    $ echo 'let f g x = g x' > test.ml
    $ ocamlopt -c test.ml
    $ objdump -d test.o
    0000000000000000 <camlTest__f_1030>:
       0:	48 89 c6             	mov    %rax,%rsi
       3:	48 89 d8             	mov    %rbx,%rax
       6:	48 8b 3e             	mov    (%rsi),%rdi
       9:	48 89 f3             	mov    %rsi,%rbx
       c:	ff e7                	jmpq   *%rdi
       e:	66 90                	xchg   %ax,%ax
Not so much.

(Yes, type specialization is a strategy used by certain whole-program optimizers, such as the MLton compiler, but this is in no way tied to the language or the type system or lack thereof. Types exist whether you name and control them or not, just like tigers and asteroids do.)


Perhaps click the words "parametric polymorphism" in that quote you keep using, and read a bit deeper. Or alternatively, scroll down and read the more detailed exposition on the subject in that same page you link. As is so often the case with technical jargon, a one-sentence definition does not necessarily capture the whole of the concept.


Yes, phrases therein such as "Parametric polymorphism allows a function or a data type to be written generically, so that it can handle values identically without depending on their type." and "A function that can evaluate to or be applied to values of different types is known as a polymorphic function." further reinforce my point that a language can support parametric polymorphism without being statically typed.

I don't see why this is not self-evident to you. Any program written in Scheme + static types is a valid program in plain Scheme. The addition of a typing system to the language does not necessarily imbue it with new capabilities, nor (as I showed above) does it necessarily alter the output of the compiler.

(Note: I distinguish "typing system" from "type constructors". Obviously adding type constructors adds capability to the language. But typing systems and type constructors exist independently of each other: Prolog has no formal type system, but has type constructors; SQL has a formal type system but no type constructors.)


Not really. There are no parameters involved in what a Scheme programmer would call a polymorphic program - instead, such programs simply range over all scheme values.

Because the values ranged over in such programs is known rather than being a parameter to the program, they are not polymorphic (in the ML sense).


such programs simply range over all scheme values

That's the parametric part.

From http://en.wikipedia.org/wiki/Polymorphism_(computer_science): If the code is written without mention of any specific type and thus can be used transparently with any number of new types, it is called parametric polymorphism. This definition makes no mention of static typing.


What is misguided - rtti or type-based dispatch - and why?


RTTI. Specifically the "runtime" part is misguided.

Languages which permit runtime type inspection are much more difficult to compile efficiently, since type information must be kept at runtime. (There is no method to identify all cases when such information may be elided, and in any such language which permits "eval", there is no such way to elide RTTI.)

Without loss of generality, any program using RTTI can be trivially transformed into one which doesn't use RTTI by tagging types, or by performing type-level computations at compile time. By performing one of these transformations, the compiler is free to generate much more efficient code.

(Technically, RTTI includes runtime type-based dispatch; e.g. object-oriented method calls. I similarly avoid such code, preferring instead less-general mechanisms such as OCaml's functors or Haskell's type classes; both of which eliminate, or, in concert with existential types or first-class modules, make the overhead of RTTI explicit. Fortunately in languages such as Java where not everything is an object, the damage of RTTI is somewhat limited.)


Exciting stuff. As an intermediate Schemer I've been looking for something like this and have had some syntax ideas, mostly about ruthlessly sticking to a minimalist prefix notation, but also a little Haskell-inspired. To illustrate briefly, I've converted one of the examples on this page to the style I've been thinking about:

https://gist.github.com/twfarland/f030cb2853cdf28b25ed

I'm not sure how possible this would be from an implementation perspective, though, that stuff is way beyond me. I just like thinking about syntax/semantics.




Applications are open for YC Winter 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: