-// Various versions of the identity function
+//// Various versions of the identity function//
// Identity for integers
// The type signature forces the function to have a more concrete type than it could have.
id_int(x) :: Int -> Int
{
return x;
-}
-
+}//
+//
// Polymorphic identity with type signature
id_poly_with(x) :: a -> a
{
return x;
-}//
+}////
-//// Polymorphic identity without type signature
-//// Type checking should figure out the type forall a . a -> a
-//id_poly_without(x)
-//{
-// return x;
-//}//
+// Polymorphic identity without type signature
+// Type checking should figure out the type forall a . a -> a
+id_poly_without(x)
+{
+ return x;
+}//
// Clumsy polymorphic identity
// Type checking should give type forall a . a -> a
-id_poly_wtf(x) :: a -> a
+id_poly_wtf(x)
{
var a = x;
var b = a;
}//
-//// Clumsy identity for integers
-//// Type checking should give type Int -> Int
-//id_int_wtf(x)
-//{
-// var a = x;
-// Int b = a;
-// var c = b;
-// return c;
-//}
+// Clumsy identity for integers
+// Type checking should give type Int -> Int
+id_int_wtf(x)
+{
+ var a = x;
+ Int b = a;
+ var c = b;
+ return c;
+}
+
+main() {return;}
\ No newline at end of file
{
return f( (x, x) );
}
+
+main() {return;}
+
+//result: right now no type error...
\ No newline at end of file
// At this point you maybe don't see what the problem is.
// Wait until you try to implement your code generator.
-var a = equal(1, 2);
-
equal(x, y)
{
return x == y;
}
+
+a() {return equal(1, 2);}
+
+main() {return;}
\ No newline at end of file
// Another variant of the polymorphic value problem.
// This is perfectly fine
-var tuple1 = (1:[], True:[]);
+tuple1() { return (1:[], True:[]); }
// This should fail.
-var l = [];
-var tuple2 = (1:l, True:l);
+l() { return [];}
+tuple2() { return (1:l, True:l);}
main() { return; }
+
+//result: does not fail!
\ No newline at end of file
// The empty list [] usually has polymorphic type forall a.[a], but you
// cannot give the variable l this type. See below what can go wrong.
-var l = [];
f()
{
+ var l = [];
// If l has polymorphic type forall a . [a], the next two lines are possible.
l = 1:l;
l = True:l;
return;
}
+main() {return;}
\ No newline at end of file
else // n > m
return gcd(m, n - m);
}
+main() {return;}
\ No newline at end of file
{
return x(x);
}
+main() {return;}
+//result: proper infinite type
\ No newline at end of file
f0(x) { return (x, x); }
f1(x) { return f0(f0(x)); }
-// f2(x) { return f1(f1(x)); }
-// f3(x) { return f2(f2(x)); }
-// f4(x) { return f3(f3(x)); }
+f2(x) { return f1(f1(x)); }
+f3(x) { return f2(f2(x)); }
+//f4(x) { return f3(f3(x)); } //using f4 gives Heap-full
// f5(x) { return f4(f4(x)); }
+main() {return;}
\ No newline at end of file
pure ((compose s3 $ compose s2 s1), subst s3 tv)
Op1Expr _ op e1 =
- abort "infereing op1" >>|
infer e1 >>= \(s1, t1) ->
fresh >>= \tv ->
let given = t1 ->> tv in
lift (unify expected given) >>= \s2 ->
pure (compose s2 s1, subst s2 tv)
- EmptyListExpr _ = abort "infereing []" >>| (\tv->(zero,tv)) <$> fresh
+ EmptyListExpr _ = (\tv->(zero,tv)) <$> fresh
TupleExpr _ (e1, e2) =
- abort "infereing (,)" >>|
infer e1 >>= \(s1, t1) ->
infer e2 >>= \(s2, t2) ->
pure (compose s2 s1, TupleType (t1,t2))
lookup f >>= \expected ->
let accST = (\(s,ts) e->infer e >>= \(s_,et)->pure (compose s_ s,ts++[et])) in
foldM accST (zero,[]) args >>= \(s1, argTs)->
- //abort (concat (["argsTs: "] ++ (map toString argTs))) >>|
fresh >>= \tv->
let given = foldr (->>) tv argTs in
lift (unify expected given) >>= \s2->
instance type VarDecl where
type (VarDecl p expected k e) =
- infer e >>= \(s, given) ->
- applySubst s >>|
+ infer e >>= \(s1, given) ->
+ applySubst s1 >>|
case expected of
Nothing = pure zero
Just expected_ = lift (unify expected_ given)
- >>|
- generalize given >>= \t ->
+ >>= \s2->
+ applySubst s2 >>|
+ let vtype = subst (compose s2 s1) given in
+ generalize vtype >>= \t ->
changeGamma (extend k t) >>|
- pure (VarDecl p (Just given) k e)
+ pure (VarDecl p (Just vtype) k e)
instance type FunDecl where
type (FunDecl p f args expected vds stmts) =