unison/unison-src/transcripts/higher-rank.md

83 lines
2.4 KiB
Markdown
Raw Permalink Normal View History

This transcript does some testing of higher-rank types. Regression tests related to higher-rank types can be added here.
```ucm:hide
scratch/main> alias.type ##Nat Nat
scratch/main> alias.type ##Text Text
scratch/main> alias.type ##IO IO
```
In this example, a higher-rank function is defined, `f`. No annotation is needed at the call-site of `f`, because the lambda is being checked against the polymorphic type `forall a . a -> a`, rather than inferred:
```unison
f : (forall a . a -> a) -> (Nat, Text)
f id = (id 1, id "hi")
> f (x -> x)
```
Another example, involving abilities. Here the ability-polymorphic function is instantiated with two different ability lists, `{}` and `{IO}`:
```unison
2024-07-01 20:28:52 +03:00
f : (forall a g . '{g} a -> '{g} a) -> () -> ()
f id _ =
2022-12-02 08:51:11 +03:00
_ = (id ('1 : '{} Nat), id ('("hi") : '{IO} Text))
()
```
Here's an example, showing that polymorphic functions can be fields of a constructor, and the functions remain polymorphic even when the field is bound to a name during pattern matching:
```unison
unique type Functor f = Functor (forall a b . (a -> b) -> f a -> f b)
Functor.map : Functor f -> (forall a b . (a -> b) -> f a -> f b)
Functor.map = cases Functor f -> f
Functor.blah : Functor f -> ()
2024-07-01 20:28:52 +03:00
Functor.blah = cases Functor f ->
g : forall a b . (a -> b) -> f a -> f b
g = f
()
```
2024-07-01 20:28:52 +03:00
This example is similar, but involves abilities:
```unison
unique ability Remote t where doRemoteStuff : t ()
2024-07-01 20:28:52 +03:00
unique type Loc = Loc (forall t a . '{Remote t} a ->{Remote t} t a)
Loc.blah : Loc -> ()
Loc.blah = cases Loc f ->
f0 : '{Remote tx} ax ->{Remote tx} tx ax
f0 = f
()
2024-07-01 20:28:52 +03:00
-- In this case, no annotation is needed since the lambda
-- is checked against a polymorphic type
2024-07-01 20:28:52 +03:00
Loc.transform : (forall t a . '{Remote t} a -> '{Remote t} a)
-> Loc -> Loc
Loc.transform nt = cases Loc f -> Loc (a -> f (nt a))
-- In this case, the annotation is needed since f' is inferred
-- on its own it won't infer the higher-rank type
2024-07-01 20:28:52 +03:00
Loc.transform2 : (forall t a . '{Remote t} a -> '{Remote t} a)
-> Loc -> Loc
2024-07-01 20:28:52 +03:00
Loc.transform2 nt = cases Loc f ->
f' : forall t a . '{Remote t} a ->{Remote t} t a
f' a = f (nt a)
2024-07-01 20:28:52 +03:00
Loc f'
```
## Types with polymorphic fields
```unison:hide
structural type HigherRanked = HigherRanked (forall a. a -> a)
```
We should be able to add and view records with higher-rank fields.
```ucm
2024-07-01 20:28:52 +03:00
scratch/main> add
scratch/main> view HigherRanked
```