mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-20 10:02:03 +03:00
1e6e125190
* Add pipeline operators * Fix tests * Change fixity, add tests * [ fix ] silence actual fixity --------- Co-authored-by: itmuckel <18561536+itmuckel@users.noreply.github.com> Co-authored-by: Guillaume Allais <guillaume.allais@ens-lyon.org>
226 lines
5.1 KiB
Idris
226 lines
5.1 KiB
Idris
module Prelude.Basics
|
|
|
|
import Builtin
|
|
|
|
import Prelude.Ops
|
|
|
|
%default total
|
|
|
|
|
|
||| `Not x` is an alias for `x -> Void`, indicating that any term of type `x`
|
|
||| leads to a contradiction. It can be used in conjunction with `void` or
|
|
||| `absurd`.
|
|
public export
|
|
Not : Type -> Type
|
|
Not x = x -> Void
|
|
|
|
-----------------------
|
|
-- UTILITY FUNCTIONS --
|
|
-----------------------
|
|
|
|
||| Manually assign a type to an expression.
|
|
||| @ a the type to assign
|
|
||| @ x the element to get the type
|
|
public export %inline
|
|
the : (0 a : Type) -> (1 x : a) -> a
|
|
the _ x = x
|
|
|
|
||| Identity function.
|
|
public export %inline
|
|
id : (x : a) -> a
|
|
id x = x
|
|
|
|
||| Function that duplicates its input
|
|
public export
|
|
dup : a -> (a, a)
|
|
dup x = (x, x)
|
|
|
|
||| Constant function. Ignores its second argument.
|
|
public export %inline
|
|
const : a -> b -> a
|
|
const x = \value => x
|
|
|
|
||| Function composition.
|
|
public export %inline %tcinline
|
|
(.) : (b -> c) -> (a -> b) -> a -> c
|
|
(.) f g = \x => f (g x)
|
|
|
|
||| Composition of a two-argument function with a single-argument one.
|
|
||| `(.:)` is like `(.)` but the second argument and the result are two-argument functions.
|
|
||| This operator is also known as "blackbird operator".
|
|
public export %inline %tcinline
|
|
(.:) : (c -> d) -> (a -> b -> c) -> a -> b -> d
|
|
(.:) = (.) . (.)
|
|
|
|
||| `on b u x y` runs the binary function b on the results of applying
|
|
||| unary function u to two arguments x and y. From the opposite perspective,
|
|
||| it transforms two inputs and combines the outputs.
|
|
|||
|
|
||| ```idris example
|
|
||| ((+) `on` f) x y = f x + f y
|
|
||| ```
|
|
|||
|
|
||| Typical usage:
|
|
|||
|
|
||| ```idris example
|
|
||| sortBy (compare `on` fst).
|
|
||| ```
|
|
public export %tcinline
|
|
on : (b -> b -> c) -> (a -> b) -> a -> a -> c
|
|
on f g = \x, y => g x `f` g y
|
|
|
|
export infixl 0 `on`
|
|
|
|
||| Takes in the first two arguments in reverse order.
|
|
||| @ f the function to flip
|
|
public export %tcinline
|
|
flip : (f : a -> b -> c) -> b -> a -> c
|
|
flip f = \x, y => f y x
|
|
|
|
||| Function application.
|
|
public export %tcinline
|
|
apply : (a -> b) -> a -> b
|
|
apply f = \a => f a
|
|
|
|
public export
|
|
curry : ((a, b) -> c) -> a -> b -> c
|
|
curry f a b = f (a, b)
|
|
|
|
public export
|
|
uncurry : (a -> b -> c) -> (a, b) -> c
|
|
uncurry f (a, b) = f a b
|
|
|
|
||| ($) is compiled specially to shortcut any tricky unification issues, but if
|
|
||| it did have a type this is what it would be, and it might be useful to
|
|
||| use directly sometimes (e.g. in higher order functions)
|
|
public export
|
|
($) : forall a, b . ((x : a) -> b x) -> (x : a) -> b x
|
|
($) f a = f a
|
|
|
|
||| Pipeline style function application, useful for chaining
|
|
||| functions into a series of transformations, reading top
|
|
||| to bottom.
|
|
|||
|
|
||| ```idris example
|
|
||| [[1], [2], [3]] |> join |> map (* 2)
|
|
||| ```
|
|
public export
|
|
(|>) : a -> (a -> b) -> b
|
|
a |> f = f a
|
|
|
|
||| Backwards pipeline style function application, similar to $.
|
|
|||
|
|
||| ```idris example
|
|
||| unpack <| "hello" ++ "world"
|
|
||| ```
|
|
public export
|
|
(<|) : (a -> b) -> a -> b
|
|
f <| a = f a
|
|
|
|
-------------------
|
|
-- PROOF HELPERS --
|
|
-------------------
|
|
|
|
||| Equality is a congruence.
|
|
public export
|
|
cong : (0 f : t -> u) -> (0 p : a = b) -> f a = f b
|
|
cong f Refl = Refl
|
|
|
|
||| Two-holed congruence.
|
|
export
|
|
-- These are natural in equational reasoning.
|
|
cong2 : (0 f : t1 -> t2 -> u) -> (0 p1 : a = b) -> (0 p2 : c = d) -> f a c = f b d
|
|
cong2 f Refl Refl = Refl
|
|
|
|
||| Dependent version of `cong`.
|
|
public export
|
|
depCong : {0 p : a -> Type} ->
|
|
(0 f : (x : a) -> p x) ->
|
|
{0 x1, x2 : a} ->
|
|
(prf : x1 = x2) ->
|
|
f x1 = f x2
|
|
depCong f Refl = Refl
|
|
|
|
||| Dependent version of `cong2`.
|
|
public export
|
|
depCong2 : {0 p : a -> Type} ->
|
|
{0 q : (x : a) -> (y : p x) -> Type} ->
|
|
(0 f : (x : a) -> (y : p x) -> q x y) ->
|
|
{0 x1, x2 : a} -> (prfX : x1 = x2) ->
|
|
{0 y1 : p x1} -> {y2 : p x2} ->
|
|
(prfY : y1 = y2) -> f x1 y1 = f x2 y2
|
|
depCong2 f Refl Refl = Refl
|
|
|
|
||| Irrelevant equalities can always be made relevant
|
|
export
|
|
irrelevantEq : (0 _ : a ~=~ b) -> a ~=~ b
|
|
irrelevantEq Refl = Refl
|
|
|
|
--------------
|
|
-- BOOLEANS --
|
|
--------------
|
|
|
|
||| Boolean Data Type.
|
|
public export
|
|
data Bool = False | True
|
|
|
|
||| Boolean NOT.
|
|
%inline
|
|
public export
|
|
not : (b : Bool) -> Bool
|
|
not True = False
|
|
not False = True
|
|
|
|
||| Boolean AND only evaluates the second argument if the first is `True`.
|
|
%inline
|
|
public export
|
|
(&&) : (b : Bool) -> Lazy Bool -> Bool
|
|
(&&) True x = x
|
|
(&&) False x = False
|
|
|
|
||| Boolean OR only evaluates the second argument if the first is `False`.
|
|
%inline
|
|
public export
|
|
(||) : (b : Bool) -> Lazy Bool -> Bool
|
|
(||) True x = True
|
|
(||) False x = x
|
|
|
|
||| Non-dependent if-then-else
|
|
%inline
|
|
public export
|
|
ifThenElse : (b : Bool) -> Lazy a -> Lazy a -> a
|
|
ifThenElse True l r = l
|
|
ifThenElse False l r = r
|
|
|
|
%inline
|
|
public export
|
|
intToBool : Int -> Bool
|
|
intToBool 0 = False
|
|
intToBool x = True
|
|
|
|
--------------
|
|
-- LISTS --
|
|
--------------
|
|
|
|
||| Generic lists.
|
|
public export
|
|
data List a =
|
|
||| Empty list
|
|
Nil
|
|
|
|
| ||| A non-empty list, consisting of a head element and the rest of the list.
|
|
(::) a (List a)
|
|
|
|
%name List xs, ys, zs
|
|
|
|
||| Snoc lists.
|
|
public export
|
|
data SnocList a =
|
|
||| Empty snoc-list
|
|
Lin
|
|
|
|
| ||| A non-empty snoc-list, consisting of the rest of the snoc-list and the final element.
|
|
(:<) (SnocList a) a
|
|
|
|
%name SnocList sx, sy, sz
|