f(x: Nat): Int = x
y: Ratio = f 1
# Erg's type checking does not necessarily enlarge the type. So this is OK.
z: Int = y
# But this is invalid.
invalid: 10..<20 = z #ERR

for! [(1, 2)], ((i, j),) =>
    k = i + 1 # OK
    print! k
for! [(1, 2)], ((i, j),) =>
    k = i + "a" # ERR
    print! k
for! zip([1], ["a"]), ((i: Int, s: Str),) =>
    k = i + 1
    l = s + "b"
    print! k, l
# ERR: i should be Int
for! zip([1], ["a"]), ((i: Str, s: Str),) =>
    k = i + "a"
    print! k
for! zip([1], ["a"]), ((i, s),) =>
    k = i + "a" # ERR
    print! k

for! zip([1+1], ["a"+"b"]), ((i, s),) => # i: Nat, s: Str
    print! i + 1
    print! s + "b"
    print! s + 1 # ERR
    print! i + "a" # ERR

for! "aaa", a =>
    print! a # OK
for! "aaa", a =>
    print! a + 1 # ERR

inty|T :> Nat, T <: Int|(x: T) = x + x
inty 0 # OK
inty 1.1 # ERR

# g: |T <: Ord and Eq and Show| T -> T
g x =
    _ = x <= x
    _ = x == x
    _ = x.__str__()
    x

g 1 # OK
g None # ERR

h x, y =
    _ = x == y
    _ = x - y
    x + y

_ = h -1, -2 # OK
_ = h 1, 2 # OK
_ = h "a", "b" # ERR

i|T|(x: T): T =
    _: Int = x
    x + "a" # ERR
i2|T|(x: T): T =
    x + "a"

_ = i 1
_ = i2 1 # ERR

_: Array!({"a", "b"}, 2) = !["a", "b"] # OK
_: Array!({"a", "b", "c"}, 2) = !["a", "b"] # OK
_: Array!({"a", "c"}, 2) = !["a", "b"] # ERR
_: Array!({"a"}, 2) = !["a", "b"] # ERR

ii _: Iterable(Iterable(Str)) = None
ii [1] # ERR
ii [[1]] # ERR
ii [["a"]]
ii ["aaa"] # Str <: Iterable Str
