1
1
mirror of https://github.com/anoma/juvix.git synced 2025-01-07 08:08:44 +03:00
juvix/tests/Compilation/positive/test056.juvix
Łukasz Czajka 34b5a14935
Improve the specialisation optimisation (#2417)
* Closes #2416 
* Closes #2401 
* Avoids generating identical specialisations by keeping a
specialisation signature for each specialised function application.
* Allows to specialise on a per-trait or per-instance basis:
```
{-# specialize: true #-}
trait
type Natural N := mkNatural {
  + : N -> N -> N;
  * : N -> N -> N;
  fromNat : Nat -> N;
};
```
or
```
{-# specialize: true #-}
instance
naturalNatI : Natural Nat := ...
```
* The above `specialize: bool` pragma actually works with any type or
function. To be able to simultaneously specify the boolean
specialisation flag and specialisation arguments, one can use
`specialize-args: [arg1, .., argn]` which works like `specialize: [arg1,
.., argn]`.
2023-10-05 10:12:48 +02:00

72 lines
1.5 KiB
Plaintext

-- argument specialization
module test056;
import Stdlib.Prelude open;
{-# specialize: [f] #-}
mymap {A B} (f : A -> B) : List A -> List B
| nil := nil
| (x :: xs) := f x :: mymap f xs;
{-# specialize: [2, 5], inline: false #-}
myf
: {A B : Type}
-> A
-> (A -> A -> B)
-> A
-> B
-> Bool
-> B
| a0 f a b true := f a0 a
| a0 f a b false := b;
{-# inline: false #-}
myf'
: {A B : Type} -> A -> (A -> A -> A -> B) -> A -> B -> B
| a0 f a b := myf a0 (f a0) a b true;
sum : List Nat -> Nat
| xs := for (acc := 0) (x in xs) {x + acc};
funa : {A : Type} -> (A -> A) -> A -> A
| {A} f a :=
let
{-# specialize-by: [f] #-}
go : Nat -> A
| zero := a
| (suc n) := f (go n);
in go 10;
{-# specialize: true #-}
type Additive A := mkAdditive {add : A -> A -> A};
type Multiplicative A :=
mkMultiplicative {mul : A -> A -> A};
addNat : Additive Nat := mkAdditive (+);
{-# specialize: true #-}
mulNat : Multiplicative Nat := mkMultiplicative (*);
{-# inline: false #-}
fadd {A} (a : Additive A) (x y : A) : A :=
Additive.add a x y;
{-# inline: false #-}
fmul {A} (m : Multiplicative A) (x y : A) : A :=
Multiplicative.mul m x y;
main : Nat :=
sum (mymap λ {x := x + 3} (1 :: 2 :: 3 :: 4 :: nil))
+ sum
(flatten
(mymap
(mymap λ {x := x + 2})
((1 :: nil) :: (2 :: 3 :: nil) :: nil)))
+ myf 3 (*) 2 5 true
+ myf 1 (+) 2 0 false
+ myf' 7 (const (+)) 2 0
+ funa ((+) 1) 5
+ fadd addNat 1 2
+ fmul mulNat 1 2;