Functions
Contents
Simply typed functions
Here are some simple functions and their types:
Pikelet> :t \x : S32 => x
S32 -> S32
Pikelet> :t \x : String => x
String -> String
Pikelet> :t \x : Char => x
Char -> Char
Note that all of these types follow the same pattern - they are the identity function! This means that if you pass a value to them, they'll return the same thing without alteration!
Pikelet> (\x : S32 => x) 42
42 : S32
Pikelet> (\x : String => x) "hi"
"hi" : String
Pikelet> (\x : Char => x) 'b'
'b' : Char
Polymorphic functions
Alas, we can't reuse one of these identity functions with other, incompatible types:
Pikelet> (\x : S32 => x) 4.0
error: found a floating point literal, but expected a type `S32`
- <repl>:1:17
1 | (\x : S32 => x) 4.0
| ^^^ the literal
Let's make this identity function polymorphic by adding a parameter for the type of the argument:
Pikelet> :t \(a : Type) (x : a) => x
(a : Type) -> a -> a
We now have a polymorphic identity function! We can specialize this function by applying a type to it:
Pikelet> (\(x : Type) (x : a) => x) String "hello"
"hello" : String
Pikelet> (\(x : Type) (x : a) => x) S32 1
1 : S32
Syntactic sugar for functions
In Pikelet, all functions take a single argument - in order to pass multiple arguments we use currying. The following functions are equivalent:
\(x : Type) (x : a) => x
\(x : Type) => \(x : a) => x
Non-dependent functions can be expressed without explicit parameter names. For example the following function types are equivalent:
(a : Type) (x : a) -> a
(a : Type) -> (x : a) -> a
(a : Type) -> a -> a