Reputation: 3244
Let's say I have a function operating on values of type base
and returning values of type base
:
(struct base ([x : Real]))
(struct child base ([y : String]))
(: fun (base base → base))
(define (fun a b)
(if (> (base-x a) (base-x b))
a
b))
The function fun
can also be restricted to the type child
, in which case it is guaranteed to return values of type child
(without modifying the code):
(: fun (child child → child))
One can also make it accept base
or child
values, and return the same type:
(: fun (case→ (base base → base)
(child child → child)))
This lacks the bound, and fails for obvious reasons:
(: fun (All (T) (T T → T)))
How can I simplify this when there are many child
types, by providing a bound to All
?
I'm looking for some syntax similar to this one:
(: fun (All (T : base) (T T → T)))
Upvotes: 2
Views: 92
Reputation: 8373
That's not supported directly, but in the latest snapshot versions, it's possible to simulate that with intersection types:
(: fun : (All (T) ((∩ base T) (∩ base T) → (∩ base T))))
Then fun
returns the most specific type it can when given mixes of base
and child
types:
> (fun (base 1) (base 2))
- : base
#<base>
> (fun (base 1) (child 2 "string"))
- : base
#<child>
> (fun (child 1 "string") (base 2))
- : base
#<base>
> (fun (child 1 "string") (child 2 "string"))
- : (∩ child base)
#<child>
> (ann (fun (child 1 "string") (child 2 "string")) child)
- : child
#<child>
And you can use a (∩ child base)
in a context that expects a child
.
Upvotes: 1