Menagerie  

The type system menagerie.

This is a scratch-pad for a bunch of half-baked type system ideas.

Scala-ish, with extras

classes:

    class type Counter (initialvalue : Int?) =
        let var count : Int = initialvalue ?? 0

        def count = count
        def inc   = count <- count + 1
        def reset = count <- 0

    class type List T (opt copyfrom : Seq T) =
        cons val capacity = 4                 // constructor value. this can be overridden when constru

        let var count   = 0
        let var storage = match copyfrom with
                              | None        -> Array initial_capacity
                              | Some seq    -> seq.ToArray ()

        let grow () =
            let newstorage = Array (storage.Length * 2)
            storage.copy_to newstorage 0
            storage <- newstorage

        def count : Int = count

        def append (val : T) =
            if storage.length == count then
                grow ()
            else
                storage[count] <- val
                count          <- count + 1

        def clear () =
            count <- 0

        def [] (index:Int) : T =
            if index < 0 or index >= count then
                throw (IndexException index count)
            storage[index]

        def iter (f : T -> Unit) =
            for i in 0..count do
                f storage[i]

    class type IndexException (index:Int) (count:Int) : Exception =
        def message = "Index {index} was out of range for collection of size {count}"

    class type Exception (opt message : String?) =
        def message = message ?? "Unknown Error"

aliases/products:

    alias type BigList = List { capacity = 500 }        // transparent alias (erases completely)

    var a  = BigList ()
    var ll = BigList l
    l.Append(4)

    alias type Pair A B = (A,B)
    alias type IntPair  = Pair Int Int

records:

    record type Point =
        field x : Int
        field y : Int

    class type Point =
        cons val x : Int
        cons val y : Int

        def x = x
        def y = y

variants:

    variant type Result T = Success Int
                          | NetworkError
                          | ArgumentError
                          | UnknownError

    (long form allows for gadt definitions, equivalent to the previous)

    variant type Result T = Success       : T    -> Result T
                          | NetworkError  : Unit -> Result T
                          | ArgumentError : Unit -> Result T
                          | UnknownError  : Unit -> Result T

vObj-flavored type structure with some extras

[someattribute]
[otherattribute]
type Foo<T> (x:int) (y:int) =
    constraint T <: int
    inherit Bar

    let x = x    // immutable data
    var x = y    // mutable data

    let x = 4

    def dosomething y z =                // method, argument types inferred
        ...
    def self.dosomething y z =           // method, argument types inferred, with optional self binding
        ...
    def x        = x
        x<-value = x <- value            // layout lets you elide the second 'def' for style reasons


Translation of a tagged sum into vObj + first class patterns

// tagged sum

variant List<A> = Nil
                | Cons (hd:A) (tl:List<A>)

encoded as primitive types

interface List =
    type List<A>
    def Cons (hd:A) (tl:List<A>) : List<A>
    def Nil                      : List<A>
    pattern Cons (l:List<A>)     : Option<A,List<A>>
    pattern Nil  (l:List<A>)     : Option<Unit>

module List_Imp : List
    val List_Tag_Nil  = 0
    val List_Tag_Cons = 1

    type List<A>
        def abstract tag : int
        def abstract hd : A
        def abstract tl : List<A>

    type List_Cons<A> (hd:A) (tl:List<A>) =
        inherit List<A>
        def override tag = List_Tag_Cons
                     hd  = hd
                     tl  = tl

    type List_Nil<A> =
        inherit List<A>
        def override tag = List_Tag_Nil
                     hd  = fail
                     tl  = fail

    def Cons (hd:A) (tl:List<A>) = List_Cons hd tl
    def Nil                      = List_Nil

    closed pattern Cons (l:List<A>) : (A,List<A>) = match l.tag with
                                                    | List_Tag_Cons  -> Some (l.hd,l.tl)
                                                    | _              -> None
                   Nil  (l:List<A>) : Unit        = match l.tag with
                                                    | List_Tag_Nil   -> Some ()
                                                    | _              -> None

Simple, F#-like type system

type data Point(x,y) =
    val x : int = x
    var y : int = y

    def distance(other : Point) : double =
        Math.sqrt ((other.x - x) ^ 2)
                  ((other.y - y) ^ 2)

type data Size(w,h) =
    val w : int = w
    var h : int = h

    def area = w * h

type class Window () =
    var location : Point
    var size     : Size

    def self.location        = location
    def self.location= value = location <- value

type record Foo =
    field thing         : Int
    field otherthing    : Double


// no anonymous records--no-one can make them work right
let x = Foo { thing = 4, otherthing = 5 }
let y = x with { thing = 5 }

type variant List a = Nil | Cons(a, List a)

// imperative sum
def sum l =
    var ret = 0
    l.each x => ret <- ret + x
    ret

Really typeclass-y

// interface definition
interface type Show
    def show () : String

// valid
record type Point
    field x : Int
    field y : Int

extend Point with Show
    def show () = "Point(#{self.x} #{self.y})"

// also valid
record type Point with Show
    field x : Int
    field y : Int
    def show () = "Point(x=#{self.x}, y=#{self.y})"

PROBLEM: these aren't as powerful as type classes because they only vary on selftype :(

however, they do reduce interface dispatch to a compile-time problem + make dictionary passing implicit

Really module-y

type [metatype] <id> =

type aliases:

    type alias foo = int            // foo is an alias for int. they are interchangeable
    type alias foo = int            // foo is an alias for int, but they have no relationship
    type alias foo <: int            // foo is a subtype of int.

products

    type Point = (dimension,dimension)
    type Size  = (dimension,dimension)
    type Rect  = (point,size)

sums

    type Shape = Rectangle      (r: Rect)
               | Circle         (c : point) (r: dimension)

abstract type members in a module

module Geometry
    abstract type Dimension
            where Dimension <: Number

    abstract val Name : string
end

import IntegerGeometry = Geometry[Dimension: int, Name: "Integer Geometry"]

Some goofy shit

signature SFoo
    def init()
end

module Foo :> SFoo
    def init()
    end

    def i_am_hidden()
    end
end

// interfaces can contain default method implementations
interface IDisposable
    def dispose()
end

type class Foo
end

type interface Bar
end

// records are like classes except:
//    - no mutation
//    - no inheritance
//    - no constructors
//    - no private members

type Quux = { }
type Foo  = Red | Yellow | Green | Color(int)
type Bar  = (x,y,z)

kinds of types:
    -                  oo: class
    - immutable algebraic: sum
    - immutable algebraic: product
    - immutable algebraic: record
    -                misc: alias (opaque, transparent, subtype, supertype ??)
    -            abstract: typeclass

type a <:> b
type a :> b
type a <: b

flavors of modules:
    - module
    - signature

mixins:
    - class mixin
    - module mixin

interface IBar
    extends IDisposable

end

mixin Serialize<T : type>
    def serialize(w : Writer)
        <| foreach (val field in T.fields if field.has_attribute?([serialize]) = 0) |>
            w.Write(<|=field.name|>)
        <| end |>
    end
end

class Bar =
    mix Foo

    [serialize] val _foo : int
    [serialize] val _bar : int
    [serialize] val _baz : int

    method init x y =
        Foo.init self
        foo = 0; bar = 1; baz = 2

    method foo        : _foo
    method foo= value : _foo = value

def foo(x) : x + 4

if foo then

end

if (foo) : bar   ???

if (foo)
    bar
end

match foo with
    | 123 ->
    | True

everything is an expression!

class Foo
    def some_method ()
    end
end

everything takes one argument!
Comments powered by Disqus