...
 
Commits (5)
Unless explicitly stated otherwise, the following license applies to all files in this repository:
Copyright 2020 Radboud University Nijmegen. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY Radboud University Nijmegen ''AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Radboud University OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of Radboud University Nijmegen.
\ No newline at end of file
# StdEnv-doc
This is an annotated version of [Clean][]'s [StdEnv][] library for use in
[Cloogle][].
All code is copyright © 1998 University of Nijmegen.
[Clean]: http://clean.cs.ru.nl
[Cloogle]: https://cloogle.org
[StdEnv]: https://svn.cs.ru.nl/repos/clean-libraries/trunk/Libraries/StdEnv/
system module StdBool
/**
* Class instances and basic functions for the Bool type.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 3.0
// Copyright 2019 University of Nijmegen
......@@ -16,8 +20,30 @@ instance fromBool {#Char} :: !Bool -> {#Char} :== code { .d 0 1 b ; jsr Bto
// Additional Logical Operators:
/**
* Logical negation.
*
* @param The boolean to negate
* @result True if the parameter was False; False if True
*/
not :: !Bool -> Bool :== code { notB }
// Not arg1
(||) infixr 2 :: !Bool Bool -> Bool // Conditional or of arg1 and arg2
(&&) infixr 3 :: !Bool Bool -> Bool // Conditional and of arg1 and arg2
/**
* Logical disjunction. The second parameter is not strict and will not be
* evaluated if the first parameter is True.
*
* @param First boolean
* @param Second boolean
* @result True iff at least one of the parameters is True
*/
(||) infixr 2 :: !Bool Bool -> Bool
/**
* Logical conjunction. The second parameter is not strict and will not be
* evaluated if the first parameter is False.
*
* @param First boolean
* @param Second boolean
* @result True iff both parameters are True
*/
(&&) infixr 3 :: !Bool Bool -> Bool
system module StdChar
/**
* Class instances and basic functions for the Char type.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 3.0
// Copyright 2019 University of Nijmegen
......@@ -24,20 +28,116 @@ instance fromChar {#Char} :: !Char -> {#Char} :== code { CtoAC }
// Additional conversions:
digitToInt :: !Char -> Int // Convert Digit into Int
toUpper :: !Char -> Char // Convert Char into an uppercase Char
toLower :: !Char -> Char // Convert Char into a lowercase Char
/**
* Converts a character from ['0'..'9'] to an integer.
*
* @param The character
* @result 0-9 if the character was from ['0'..'9'], otherwise another Int
*/
digitToInt :: !Char -> Int
/**
* Converts a character to uppercase.
*
* @param The character
* @result The same character, with bit 5 cleared
*/
toUpper :: !Char -> Char
/**
* Converts a character to lowercase.
*
* @param The character
* @result The same character, with bit 5 set
*/
toLower :: !Char -> Char
// Tests on Characters:
isUpper :: !Char -> Bool // True if arg1 is an uppercase character
isLower :: !Char -> Bool // True if arg1 is a lowercase character
isAlpha :: !Char -> Bool // True if arg1 is a letter
isAlphanum :: !Char -> Bool // True if arg1 is an alphanumerical character
isDigit :: !Char -> Bool // True if arg1 is a digit
isOctDigit :: !Char -> Bool // True if arg1 is a digit
isHexDigit :: !Char -> Bool // True if arg1 is a digit
isSpace :: !Char -> Bool // True if arg1 is a space, tab etc
isControl :: !Char -> Bool // True if arg1 is a control character
isPrint :: !Char -> Bool // True if arg1 is a printable character
isAscii :: !Char -> Bool // True if arg1 is a 7 bit ASCII character
/**
* Check for uppercase
*
* @param The character
* @result True iff the parameter is from ['A'..'Z']
*/
isUpper :: !Char -> Bool
/**
* Check for lowercase
*
* @param The character
* @result True iff the parameter is from ['a'..'z']
*/
isLower :: !Char -> Bool
/**
* Check for an alphabetic character
*
* @param The character
* @result True iff the parameter is from ['a'..'z'] ++ ['A'..'Z']
*/
isAlpha :: !Char -> Bool
/**
* Check for an alphabetic or numerical character
*
* @param The character
* @result True iff the parameter is from ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9']
*/
isAlphanum :: !Char -> Bool
/**
* Check for a numerical character
*
* @param The character
* @result True iff the parameter is from ['0'..'9']
*/
isDigit :: !Char -> Bool
/**
* Check for an octal digit
*
* @param The character
* @result True iff the parameter is from ['0'..'7']
*/
isOctDigit :: !Char -> Bool
/**
* Check for a hexadecimal digit
*
* @param The character
* @result True iff the parameter is from ['0'..'9'] ++ ['a'..'f'] ++ ['A'..'F']
*/
isHexDigit :: !Char -> Bool
/**
* Check for whitespace
*
* @param The character
* @result True iff the parameter is one of ' ', '\t', '\n', '\r', '\f', '\v'
*/
isSpace :: !Char -> Bool
/**
* Check for an ASCII control character
*
* @param The character
* @result True iff the parameter is from ['\x00'..'\x1f'] ++ ['\x7f']
*/
isControl :: !Char -> Bool
/**
* Check for a printable ASCII character
*
* @param The character
* @result True iff the parameter is from [' '..'~']
*/
isPrint :: !Char -> Bool
/**
* Check for a 7-bit ASCII character
*
* @param The character
* @result True iff the integer value of the parameter is less than 128
*/
isAscii :: !Char -> Bool
definition module StdCharList
/**
* Basic functions for manipulating lists of characters.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 2.0
// Copyright 1998 University of Nijmegen
// ****************************************************************************************
cjustify :: !.Int ![.Char] -> .[Char] // Center [Char] in field with width arg1
ljustify :: !.Int ![.Char] -> .[Char] // Left justify [Char] in field with width arg1
rjustify :: !.Int ![.Char] -> [Char] // Right justify [Char] in field with width arg1
/**
* Center-align a text with spaces, s.t. the right margin is 0 or 1 spaces
* longer than the left margin.
*
* @param The minimum length of the result
* @param The text to center
* @result A list of max(|param 2|, param 1), with param 2 surrounded by spaces
*/
cjustify :: !.Int ![.Char] -> .[Char]
/**
* Left-align a text with spaces
*
* @param The minimum length of the result
* @param The text to align
* @result A list of max(|param 2|, param 1), with spaces appended to param 2
*/
ljustify :: !.Int ![.Char] -> .[Char]
/**
* Right-align a text with spaces
*
* @param The minimum length of the result
* @param The text to align
* @result A list of max(|param 2|, param 1), with spaces prepended to param 2
*/
rjustify :: !.Int ![.Char] -> [Char]
/**
* Concatenate a list of texts, interspersing it with newlines
*
* @param The texts
* @result All texts concatenated, with newlines in between
*/
flatlines :: ![[u:Char]] -> [u:Char]
flatlines :: ![[u:Char]] -> [u:Char] // Concatenate by adding newlines
mklines :: ![Char] -> [[Char]] // Split in lines removing newlines
/**
* Split a text on newlines
*
* @param The text
* @result A list of texts without newlines
*/
mklines :: ![Char] -> [[Char]]
spaces :: !.Int -> .[Char] // Make [Char] containing n space characters
/**
* A list of a number of ' ' characters
*
* @param The number of characters
* @result A list of param 1 spaces
*/
spaces :: !.Int -> .[Char]
definition module StdClass
/**
* Meta-classes with derived functions.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 2.0
// Copyright 1998 University of Nijmegen
......@@ -12,40 +16,73 @@ from StdBool import not
// For the time-being, macro definitions are used for this purpose
// This may cause misleading error messages in case of type errors
//* Meta-class describing interval types with an absolute zero.
class PlusMin a | + , - , zero a
//* Meta-class describing ratio types.
class MultDiv a | * , / , one a
//* Meta-class describing arithmetical types.
class Arith a | PlusMin , MultDiv , abs , sign , ~ a
//* Meta-class describing types that can be incremented and decremented.
class IncDec a | + , - , one , zero a
where
//* Increment a value by one.
inc :: !a -> a | + , one a
inc x :== x + one
//* Decrement a value by one.
dec :: !a -> a | - , one a
dec x :== x - one
//* Meta-class describing types that can be enumerated.
class Enum a | < , IncDec a
/**
* Equality.
* @var The type for which values can be equated
*/
class Eq a | == a
where
/**
* Inequality.
* @result True iff the parameters are not equal
*/
(<>) infix 4 :: !a !a -> Bool | Eq a
(<>) x y :== not (x == y)
/**
* Ordering.
* @var The type that can be ordered.
*/
class Ord a | < a
where
/**
* Greater than.
* @result True iff the first value is strictly greater than the second value.
*/
(>) infix 4 :: !a !a -> Bool | Ord a
(>) x y :== y < x
/**
* Smaller than or equal to.
* @result True iff the first value is smaller than or equal to the second value.
*/
(<=) infix 4 :: !a !a -> Bool | Ord a
(<=) x y :== not (y<x)
/**
* Greater than or equal to.
* @result True iff the first value is greater than or equal to the second value.
*/
(>=) infix 4 :: !a !a -> Bool | Ord a
(>=) x y :== not (x<y)
//* The minimum of two values.
min::!a !a -> a | Ord a
min x y :== case (x<y) of True = x; _ = y
//* The maximum of two values.
max::!a !a -> a | Ord a
max x y :== case (x<y) of True = y; _ = x
definition module StdDebug
/**
* Functions that write intermediate results to stderr for debugging purposes.
*/
// ********************************************************
// Concurrent Clean Standard Library Module Version 2.0
// Copyright 1998 University of Nijmegen
......@@ -12,16 +16,48 @@ from StdString import instance toString {#Char},instance toString Int
// The following functions should only be used for debugging,
// because these functions have side effects
trace :: !msg .a -> .a | toString msg // write toString msg to stderr
// before evaluating a
special msg={#Char}; msg=Int
trace_n :: !msg .a -> .a | toString msg // write toString msg and newline to stderr
// before evaluating a
special msg={#Char}; msg=Int
trace_t :: !msg -> Bool | toString msg // write toString msg to stderr
// result is True
special msg={#Char}; msg=Int
trace_tn :: !msg -> Bool | toString msg // write toString msg and newline to stderr
// result is True
special msg={#Char}; msg=Int
/**
* Write a message to stderr before returning a value.
*
* @param The message to write to stderr
* @param The value to return
* @result Param 2
*/
trace :: !msg .a -> .a | toString msg special msg={#Char}; msg=Int
/**
* Write a message and a newline to stderr before returning a value.
*
* @param The message to write to stderr
* @param The value to return
* @result Param 2
*/
trace_n :: !msg .a -> .a | toString msg special msg={#Char}; msg=Int
/**
* Write a message to stderr and return True. This is useful in guards, for
* example:
*
* ```
* square x
* | trace_t x = x * x
* ```
*
* @param The message to write to stderr
* @result True
*/
trace_t :: !msg -> Bool | toString msg special msg={#Char}; msg=Int
/**
* Write a message and a newline to stderr and return True. This is useful in
* guards, for example:
*
* ```
* square x
* | trace_tn x = x * x
* ```
*
* @param The message to write to stderr
* @result True
*/
trace_tn :: !msg -> Bool | toString msg special msg={#Char}; msg=Int
definition module StdEnum
/**
* This module must be imported if dotdot expressions are used.
* Then, the following constructs can be used:
*
* - `[from .. ]` -> `{{_from}} from`
* - `[from .. to]` -> `{{_from_to}} from to`
* - `[from, then .. ]` -> `{{_from_then}} from then`
* - `[from, then .. to]` -> `{{_from_then_to}} from then to`
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 2.0
// Copyright 1998 University of Nijmegen
// ****************************************************************************************
/*
This module must be imported if dotdot expressions are used
[from .. ] -> _from from
[from .. to] -> _from_to from to
[from, then .. ] -> _from_then from then
[from, then .. to] -> _from_then_to from then to
*/
import _SystemEnum
definition module StdEnv
/**
* Clean's official Standard Environment library.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 3.0
// Copyright 2018 Radboud University
......
system module StdFile
/**
* Functions to manipulate the file system with the File type.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 3.0
// Copyright 2019 University of Nijmegen
......@@ -7,110 +11,206 @@ system module StdFile
// File modes synonyms
FReadText :== 0 // Read from a text file
FWriteText :== 1 // Write to a text file
FAppendText :== 2 // Append to an existing text file
FReadData :== 3 // Read from a data file
FWriteData :== 4 // Write to a data file
FAppendData :== 5 // Append to an existing data file
//* File mode: read text
FReadText :== 0
//* File mode: write text
FWriteText :== 1
//* File mode: append text
FAppendText :== 2
//* File mode: read data
FReadData :== 3
//* File mode: write data
FWriteData :== 4
//* File mode: append data
FAppendData :== 5
// Seek modes synonyms
FSeekSet :== 0 // New position is the seek offset
FSeekCur :== 1 // New position is the current position plus the seek offset
FSeekEnd :== 2 // New position is the size of the file plus the seek offset
//* Seek mode: the new position is the seek offset
FSeekSet :== 0
:: *Files
//* Seek mode: the new position is the current position plus the seek offset
FSeekCur :== 1
// Acces to the FileSystem (Files)
//* Seek mode: the new position is the size of the file plus the seek offset
FSeekEnd :== 2
/**
* The filesystem environment, independent from *World. This type can only be
* used through the FileSystem and FileEnv classes.
*/
:: *Files
/**
* Access to the filesystem.
*
* @var The unique type that is used to ensure purity.
*/
class FileSystem f where
/**
* Opens a file for the first time in a certain mode.
* @param The filename
* @param The mode (read / write / append; text / data)
* @param The {{`FileSystem`}} (usually {{`World`}})
* @result A boolean indicating success
* @result The {{`File`}}
* @result The new {{`FileSystem`}}
*/
fopen :: !{#Char} !Int !*f -> (!Bool,!*File,!*f)
/* Opens a file for the first time in a certain mode (read, write or append, text or data).
The boolean output parameter reports success or failure. */
/**
* Closes a file.
* @param The {{`File`}}
* @param The {{`FileSystem`}}
* @result A boolean indicating success
* @result The new {{`FileSystem`}}
*/
fclose :: !*File !*f -> (!Bool,!*f)
/* Closes a file */
//* Open the 'Console' for reading and writing.
stdio :: !*f -> (!*File,!*f)
/* Open the 'Console' for reading and writing. */
/**
* With `sfopen` a file can be opened for reading more than once. On a file
* opened by `sfopen` only the operations beginning with `sf` can be used.
* The `sf...` operations work just like the corresponding `f...`
* operations. They can't be used for files opened with {{`fopen`} or
* {{`freopen`}}.
*
* @param The filename
* @param The mode (read; text / data)
* @param The {{`FileSystem`}} (usually {{`World`}})
* @result A boolean indicating success
* @result The new {{`File`}}
* @result The new {{`FileSystem`}}
*/
sfopen :: !{#Char} !Int !*f -> (!Bool,!File,!*f)
/* With sfopen a file can be opened for reading more than once.
On a file opened by sfopen only the operations beginning with sf can be used.
The sf... operations work just like the corresponding f... operations.
They can't be used for files opened with fopen or freopen. */
instance FileSystem Files
instance FileSystem World
/**
* An environment in which files can be dealt with.
*
* @var The unique type that is used to ensure purity.
*/
class FileEnv env where
accFiles :: !.(*Files -> (.x,*Files)) !*env -> (!.x,!*env)
appFiles :: !.(*Files -> *Files) !*env -> *env
instance FileEnv World
// openfiles :: !*World -> (!*Files,!*World) // no longer supported
// closefiles :: !*Files !*World -> *World // no longer supported
/**
* Re-opens an open file in a possibly different mode.
* @param The file
* @param The new mode
* @result A boolean indicating successful closing before reopening
* @result The new file
*/
freopen :: !*File !Int -> (!Bool,!*File) :== code { .d 0 3 f i ; jsr reopenF ; .o 0 3 b f }
/* Re-opens an open file in a possibly different mode.
The boolean indicates whether the file was successfully closed before reopening. */
// Reading from a File:
/**
* Reads a character from a text file or a byte from a datafile.
* @result A boolean indicating success
* @result The read character
*/
freadc :: !*File -> (!Bool,!Char,!*File) :== code { .d 0 2 f ; jsr readFC ; .o 0 4 b c f }
/* Reads a character from a text file or a byte from a datafile.
The boolean indicates succes or failure */
/**
* Reads an Integer from a textfile by skipping spaces, tabs and newlines and
* then reading digits, which may be preceeded by a plus or minus sign.
* From a datafile `freadi` will just read four bytes (a Clean Int).
* @result A boolean indicating success
* @result The read integer
*/
freadi :: !*File -> (!Bool,!Int,!*File) :== code { .d 0 2 f ; jsr readFI ; .o 0 4 b i f }
/* Reads an Integer from a textfile by skipping spaces, tabs and newlines and
then reading digits, which may be preceeded by a plus or minus sign.
From a datafile freadi will just read four bytes (a Clean Int). */
/**
* Reads a Real from a textfile by skipping spaces, tabs and newlines and then
* reading a character representation of a Real number.
* From a datafile `freadr` will just read eight bytes (a Clean Real).
* @result A boolean indicating success
* @result The read real
*/
freadr :: !*File -> (!Bool,!Real,!*File) :== code { .d 0 2 f ; jsr readFR ; .o 0 5 b r f }
/* Reads a Real from a textfile by skipping spaces, tabs and newlines and then
reading a character representation of a Real number.
From a datafile freadr will just read eight bytes (a Clean Real). */
/**
* Reads n characters from a text or data file, which are returned as a String.
* If the file doesn't contain n characters the file will be read to the end
* of the file. An empty String is returned if no characters can be read.
* @param The file
* @param The amount of characters to read
* @result The read string
* @result The file
*/
freads :: ! *File !Int -> (!*{#Char},!*File) :== code { .d 0 3 f i ; jsr readFS ; .o 1 2 f }
/* Reads n characters from a text or data file, which are returned as a String.
If the file doesn't contain n characters the file will be read to the end
of the file. An empty String is returned if no characters can be read. */
/**
* Reads `n` characters from a text or data file, which are returned in the
* string `arg3` at positions `arg1`..`arg1+arg2-1`. If the file doesn't
* contain `arg2` characters the file will be read to the end of the file, and
* the part of the string `arg3` that could not be read will not be changed.
*
* @param The start of the substring to modify
* @param The length of the substring
* @param The string to modify
* @result The number of characters read
* @result The modified string
*/
freadsubstring :: !Int !Int !*{#Char} !*File -> (!Int,!*{#Char},!*File) :== code { .d 1 4 i i f ; jsr readFString ; .o 1 3 i f }
/*
Reads n characters from a text or data file, which are returned in the string
arg3 at positions arg1..arg1+arg2-1. If the file doesn't contain arg2 characters
the file will be read to the end of the file, and the part of the string arg3 that
could not be read will not be changed. The number of characters read, the modified
string and the file are returned.
*/
/**
* Reads a line from a textfile, including a newline character, except for the
* last line. `freadline` cannot be used on data files.
*/
freadline :: !*File -> (!*{#Char},!*File) :== code { .d 0 2 f ; jsr readLineF ; .o 1 2 f }
/* Reads a line from a textfile. (including a newline character, except for the last
line) freadline cannot be used on data files. */
// Writing to a File:
/**
* Writes a character to a textfile.
* To a datafile fwritec writes one byte (a Clean Char).
*/
fwritec :: !Char !*File -> *File :== code { .d 0 3 c f ; jsr writeFC ; .o 0 2 f }
/* Writes a character to a textfile.
To a datafile fwritec writes one byte (a Clean Char). */
/**
* Writes an Integer (its textual representation) to a text file. To a datafile
* fwritei writes four bytes (a Clean Int).
*/
fwritei :: !Int !*File -> *File :== code { .d 0 3 i f ; jsr writeFI ; .o 0 2 f }
/* Writes an Integer (its textual representation) to a text file.
To a datafile fwritei writes four bytes (a Clean Int). */
/**
* Writes a Real (its textual representation) to a text file. To a datafile
* fwriter writes eight bytes (a Clean Real).
*/
fwriter :: !Real !*File -> *File :== code { .d 0 4 r f ; jsr writeFR ; .o 0 2 f }
/* Writes a Real (its textual representation) to a text file.
To a datafile fwriter writes eight bytes (a Clean Real). */
//* Writes a String to a text or data file.
fwrites :: !{#Char} !*File -> *File :== code { .d 1 2 f ; jsr writeFS ; .o 0 2 f }
/* Writes a String to a text or data file. */
/**
* Writes the characters at positions `arg1`..`arg1+arg2-1` of string `arg3` to
* a text or data file.
*/
fwritesubstring :: !Int !Int !{#Char} !*File -> *File :== code { .d 1 4 i i f ; jsr writeFString ; .o 0 2 f }
/* Writes the characters at positions arg1..arg1+arg2-1 of string arg3 to
a text or data file. */
/**
* Overloaded write to file. This allows you to chain write operations, like:
* `# f = f <<< "X is: " <<< x <<< "; y is: " <<< y <<< "\n"`
*
* @var The type that can be written to a file
* @param The File
* @param The thing to write
* @result The new File
*/
class (<<<) infixl a :: !*File !a -> *File
/* Overloaded write to file */
instance <<< Int :: !*File !Int -> *File :== code { push_b 2 ; update_b 2 3 ; update_b 1 2 ; updatepop_b 0 1 ; .d 0 3 i f ; jsr writeFI ; .o 0 2 f }
instance <<< Char :: !*File !Char -> *File :== code { push_b 2 ; update_b 2 3 ; update_b 1 2 ; updatepop_b 0 1 ; .d 0 3 c f ; jsr writeFC ; .o 0 2 f }
......@@ -119,24 +219,35 @@ instance <<< Real :: !*File !Real -> *File :== code { push_b 3 ; push_b 3
// Testing:
/**
* @result Whether end-of-file has been reached
*/
fend :: !*File -> (!Bool,!*File) :== code { .d 0 2 f ; jsr endF ; .o 0 3 b f }
/* Tests for end-of-file. */
/**
* @result Whether an error has occurred during previous file I/O operations
*/
ferror :: !*File -> (!Bool,!*File) :== code { .d 0 2 f ; jsr errorF ; .o 0 3 b f }
/* Has an error occurred during previous file I/O operations? */
/**
* @result The current position of the file pointer as an Integer. This
* position can be used later on for the fseek function.
*/
fposition :: !*File -> (!Int,!*File) :== code { .d 0 2 f ; jsr positionF ; .o 0 3 i f }
/* returns the current position of the file poInter as an Integer.
This position can be used later on for the fseek function. */
/**
* Move to a different position in the file
*
* @param The offset
* @param A seek mode ({{`FSeekSet`}}, {{`FSeekCur`}} or {{`FSeekEnd`}})
* @result True iff the seek was successful
*/
fseek :: !*File !Int !Int -> (!Bool,!*File) :== code { .d 0 4 f i i ; jsr seekF ; .o 0 3 b f }
/* Move to a different position in the file, the first Integer argument is the offset,
the second argument is a seek mode. (see above). True is returned if successful. */
// Predefined files.
//* Open the 'Errors' file for writing only. May be opened more than once.
stderr :: *File :== code { .d 0 0 ; jsr stderrF ; .o 0 2 f }
/* Open the 'Errors' file for writing only. May be opened more than once. */
// Opening and reading Shared Files:
......@@ -155,7 +266,8 @@ sfposition :: !File -> Int :== code { .d 0 2 f ; jsr positionSF ; .o
// Convert a *File into:
//* Change a file so that from now it can only be used with `sf...` operations.
fshare :: !*File -> File :== code { .d 0 2 f ; jsr shareF ; .o 0 2 f }
/* Change a file so that from now it can only be used with sf... operations. */
//* Flush all I/O operations on a file.
fflush :: !*File -> (!Bool,!*File) :== code { .d 0 2 f ; jsr flushF ; .o 0 3 bf }
definition module StdFunc
/**
* A number of general functions and functions dealing with functions.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 3.0
// Copyright 2018 Radboud University
......@@ -9,15 +13,38 @@ import StdFunctions
// Some handy functions for transforming unique states:
seq :: ![.(.s -> .s)] .s -> .s // fn-1 (..(f1 (f0 x))..)
seqList :: ![St .s .a] .s -> ([.a],.s) // fn-1 (..(f1 (f0 x))..)
/**
* Iterate a list of state functions.
*
* @param The functions
* @param The initial state
* @result The final state
*/
seq :: ![.(.s -> .s)] .s -> .s
/**
* Iterate a list of state functions with result
*
* @param The functions
* @param The initial state
* @result A list of results from the state function and the final state
*/
seqList :: ![St .s .a] .s -> ([.a],.s)
//* A function that updates a state and produces a result.
:: St s a :== s -> *(a,s)
// monadic style:
(`bind`) infix 0 // :: w:(St .s .a) v:(.a -> .(St .s .b)) -> u:(St .s .b), [u <= v, u <= w]
/**
* Monadic bind for the {{`St`}} type.
* @type w:(St .s .a) v:(.a -> .(St .s .b)) -> u:(St .s .b), [u <= v, u <= w]
*/
(`bind`) infix 0
(`bind`) f g :== \st0 -> let (r,st1) = f st0 in g r st1
// return :: u:a -> u:(St .s u:a)
/**
* Monadic return for the {{`St`}} type.
* @type u:a -> u:(St .s u:a)
*/
return r :== \s -> (r,s)
......@@ -5,16 +5,29 @@ definition module StdFunctions
// Copyright 2018 Radboud University
// ****************************************************************************************
id :: !.a -> .a // identity function
const :: !.a .b -> .a // constant function
//* The identity function.
id :: !.a -> .a
//* Always returns the first argument.
const :: !.a .b -> .a
//flip :: !.(.a -> .(.b -> .c)) .b .a -> .c // Flip arguments
/**
* Flips the arguments of a function. This is useful in function compositions.
* @type !.(.a -> .(.b -> .c)) .b .a -> .c
*/
flip f a b :== f b a
(o) infixr 9 // :: u:(.a -> .b) u:(.c -> .a) -> u:(.c -> .b) // Function composition
/**
* Function composition: apply `f` after `g`.
* @type u:(.a -> .b) u:(.c -> .a) -> u:(.c -> .b)
*/
(o) infixr 9
(o) f g :== \ x -> f (g x)
twice :: !(.a -> .a) .a -> .a // f (f x)
while :: !(a -> .Bool) (a -> a) a -> a // while (p x) f (f x)
until :: !(a -> .Bool) (a -> a) a -> a // f (f x) until (p x)
iter :: !Int (.a -> .a) .a -> .a // f (f..(f x)..)
//* Apply the function argument twice.
twice :: !(.a -> .a) .a -> .a
//* Apply the second argument as long as the first argument holds.
while :: !(a -> .Bool) (a -> a) a -> a
//* Apply the second argument until the first argument holds.
until :: !(a -> .Bool) (a -> a) a -> a
//* Apply a function a number of times.
iter :: !Int (.a -> .a) .a -> .a
system module StdInt
/**
* Class instances and basic functions for the Int type.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 2.0
// Copyright 1998 University of Nijmegen
......@@ -49,17 +53,65 @@ instance lcm Int // Least common multiple
// Operators on Bits:
/**
* Bitwise disjunction.
*
* @param The first integer
* @param The second integer
* @result An integer with exactly those bits set that at least one of the parameters has set
*/
(bitor) infixl 6 :: !Int !Int -> Int :== code { or% }
// Bitwise Or of arg1 and arg2
/**
* Bitwise conjunction.
*
* @param The first integer
* @param The second integer
* @result An integer with exactly those bits set that both of the parameters have set
*/
(bitand) infixl 6 :: !Int !Int -> Int :== code { and% }
// Bitwise And of arg1 and arg2
/**
* Bitwise exclusive disjunction.
*
* @param The first integer
* @param The second integer
* @result An integer with exactly those bits set that exactly one of the parameters has set
*/
(bitxor) infixl 6 :: !Int !Int -> Int :== code { xor% }
// Exclusive-Or arg1 with mask arg2
/**
* Shift an integer to the left.
*
* @param The integer to shift
* @param The number of places to shift
* @result The result of the bitshift
*/
(<<) infix 7 :: !Int !Int -> Int :== code { shiftl% }
// Shift arg1 to the left arg2 bit places
/**
* Shift an integer to the right.
*
* @param The integer to shift
* @param The number of places to shift
* @result The result of the bitshift
*/
(>>) infix 7 :: !Int !Int -> Int :== code { shiftr% }
// Shift arg1 to the right arg2 bit places
/**
* Bitwise logical negation.
*
* @param An integer
* @param The one's complement of the parameter
*/
bitnot :: !Int -> Int :== code { not% }
// One's complement of arg1
IF_INT_64_OR_32 int64 int32 :== int32;
/**
* Compile-time macro to check for the integer length of the system.
*
* @type .a .a -> .a
* @param The value if the platform is 64-bit
* @param The value if the platform is 32-bit
* @result Either of the parameters, depending on the platform
*/
IF_INT_64_OR_32 int64 int32 :== int64;
definition module StdList
/**
* Basic operations on lists.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 2.2
// Copyright 1998-2006 University of Nijmegen
......@@ -30,112 +34,272 @@ instance fromString [x] | fromChar x // Convert String via [Char] into [x]
// List Operators:
(!!) infixl 9 :: ![.a] !Int -> .a // Get nth element of the list
(++) infixr 5 :: ![.a] u:[.a] -> u:[.a] // Append args
flatten :: ![[.a]] -> [.a] // e0 ++ e1 ++ ... ++ e##
isEmpty :: ![.a] -> Bool // [] ?
//* The nth element of a list.
(!!) infixl 9 :: ![.a] !Int -> .a
//* Concatenate two lists.
(++) infixr 5 :: ![.a] u:[.a] -> u:[.a]
//* Concatenate a list of lists.
flatten :: ![[.a]] -> [.a]
//* True iff the list is empty.
isEmpty :: ![.a] -> Bool
// List breaking or permuting functions:
hd :: ![.a] -> .a // Head of the list
tl :: !u:[.a] -> u:[.a] // Tail of the list
last :: ![.a] -> .a // Last element of the list
init :: ![.a] -> [.a] // Remove last element of the list
take :: !Int [.a] -> [.a] // Take first arg1 elements of the list
takeWhile :: (a -> .Bool) !.[a] -> .[a] // Take elements while pred holds
drop :: !Int !u:[.a] -> u:[.a] // Drop first arg1 elements from the list
dropWhile :: (a -> .Bool) !u:[a] -> u:[a] // Drop elements while pred holds
span :: (a -> .Bool) !u:[a] -> (.[a],u:[a]) // (takeWhile list,dropWhile list)
filter :: (a -> .Bool) !.[a] -> .[a] // Drop all elements not satisfying pred
reverse :: ![.a] -> [.a] // Reverse the list
insert :: (a -> a -> .Bool) a !u:[a] -> u:[a] // Insert arg2 when pred arg2 elem holds
insertAt :: !Int .a u:[.a] -> u:[.a] // Insert arg2 on position arg1 in list
removeAt :: !Int !u:[.a] -> u:[.a] // Remove arg2!!arg1 from list
updateAt :: !Int .a !u:[.a] -> u:[.a] // Replace list!!arg1 by arg2
//* The head (first element) of a list.
hd :: ![.a] -> .a
//* The tail (everything except the first element) of a list.
tl :: !u:[.a] -> u:[.a]
//* The last element of a list.
last :: ![.a] -> .a
//* Everything except the last element of a list.
init :: ![.a] -> [.a]
/**
* Take a number of elements from the start of a list. When there are not
* enough elements, the original list is returned.
*/
take :: !Int [.a] -> [.a]
//* Take elements from the start of a list as long as a predicate holds.
takeWhile :: (a -> .Bool) !.[a] -> .[a]
/**
* Drop a number of elements from the start of a list. When there are not
* enough elements, `[]` is returned.
*/
drop :: !Int !u:[.a] -> u:[.a]
//* Drop elements from the start of a list as long as a predicate holds.
dropWhile :: (a -> .Bool) !u:[a] -> u:[a]
/**
* @param A predicate `p`
* @param A list `xs`
* @result `{{takeWhile}} p xs`
* @result `{{dropWhile}} p xs`
*/
span :: (a -> .Bool) !u:[a] -> (.[a],u:[a])
/**
* Filter a list using a predicate.
* @result The list containing exactly those elements for which the predicate
* holds.
*/
filter :: (a -> .Bool) !.[a] -> .[a]
//* Reverse a list.
reverse :: ![.a] -> [.a]
/**
* Insert an element when a certain predicate holds. When the predicate does
* not hold for any element, the new element is added to the end of the list.
* @param The predicate on the new element and the existing element
* @param The new element
* @param The list
*/
insert :: (a -> a -> .Bool) a !u:[a] -> u:[a]
/**
* Insert an element at an index. When the index is out-of-range, add it to the
* end of the list.
*/
insertAt :: !Int .a u:[.a] -> u:[.a]
/**
* Remove an element at a certain index from a list. When the index is
* out-of-range, the original list is returned.
*/
removeAt :: !Int !u:[.a] -> u:[.a]
/**
* Replace an element at a certain index. When the index is out-of-range, the
* original list is returned.
*/
updateAt :: !Int .a !u:[.a] -> u:[.a]
/**
* @param An index `n` of the list
* @param The list `xs`
* @result `{{take}} n xs`
* @result `{{drop}} n xs`
*/
splitAt :: !Int u:[.a] -> ([.a],u:[.a]) // (take n list,drop n list)
// Creating lists:
map :: (.a -> .b) ![.a] -> [.b] // [f e0,f e1,f e2,...
iterate :: (a -> a) a -> .[a] // [a,f a,f (f a),...
indexList :: !.[a] -> [Int] // [0..maxIndex list]
repeatn :: !.Int a -> .[a] // [e0,e0,...,e0] of length n
repeat :: a -> [a] // [e0,e0,...
unzip :: ![(.a,.b)] -> ([.a],[.b]) // ([a0,a1,...],[b0,b1,...])
zip2 :: ![.a] [.b] -> [(.a,.b)] // [(a0,b0),(a1,b1),...
zip :: !(![.a],[.b]) -> [(.a,.b)] // [(a0,b0),(a1,b1),...
diag2 :: !.[a] .[b] -> [.(a,b)] // [(a0,b0),(a1,b0),(a0,b1),...
diag3 :: !.[a] .[b] .[c] -> [.(a,b,c)] // [(a0,b0,c0),(a1,b0,c0),...
//* Apply a function to every element of a list.
map :: (.a -> .b) ![.a] -> [.b]
// Folding and scanning:
/**
* Repeatedly apply a function.
* @param The function `f`
* @param The initial value `x`
* @result `[x, f x, f (f x), f (f (f x)), ...]`
*/
iterate :: (a -> a) a -> .[a]
/**
* Create a list of indices for an existing list.
* @param The list `xs`
* @result `[0..{{length}} xs - 1]`
*/
indexList :: !.[a] -> [Int]
//* Create a list of `n` elements `x`.
repeatn :: !.Int a -> .[a]
//* Repeat an element indefinitely.
repeat :: a -> [a]
//* Unzip a list of tuples to a tuple of lists.
unzip :: ![(.a,.b)] -> ([.a],[.b])
// for efficiency reasons, foldl and foldr are macros, so that applications of these functions will be inlined
/**
* Zip two lists to a list of tuples. The result list has the length of the
* shortest of the two original lists.
* Also see {{`zip`}}.
*/
zip2 :: ![.a] [.b] -> [(.a,.b)]
// foldl :: (.a -> .(.b -> .a)) .a ![.b] -> .a // op(...(op (op (op r e0) e1)...e##)
//* Same as {{`zip2`}}, but for two lists in a tuple.
zip :: !(![.a],[.b]) -> [(.a,.b)]
//* Diagonally create the Cartesian product for two lists.
diag2 :: !.[a] .[b] -> [.(a,b)]
//* Diagonally create the Cartesian product for three lists.
diag3 :: !.[a] .[b] .[c] -> [.(a,b,c)]
// Folding and scanning:
/**
* Replace all list constructors with a left-associative operator.
* For efficiency reasons, `foldl` is a macro, so that applications of this
* functions are inlined.
* Also see `foldr`.
*
* @param The operator (substitute for `Cons`)
* @param The substitute for `Nil`
* @param The list
* @result `op (... (op (op (op r e0) e1) e2) ...) en`
* @type (.a -> .(.b -> .a)) .a ![.b] -> .a
*/
foldl op r l :== foldl r l
where
foldl r [] = r
foldl r [a:x] = foldl (op r a) x
// foldr :: (.a -> .(.b -> .b)) .b ![.a] -> .b // op e0 (op e1(...(op e## r)...)
/**
* Replace all list constructors with a right-associative operator.
* For efficiency reasons, `foldr` is a macro, so that applications of this
* functions are inlined.
* Also see `foldl`.
*
* @param The operator (substitute for `Cons`)
* @param The substitute for `Nil`
* @param The list
* @result `op e0 (op e1 (... (op en r) ...))`
* @type (.a -> .(.b -> .b)) .b ![.a] -> .b
*/
foldr op r l :== foldr l
where
foldr [] = r
foldr [a:x] = op a (foldr x)
scan :: (a -> .(.b -> a)) a ![.b] -> .[a] // [r,op r e0,op (op r e0) e1,...
/**
* `scan` is like {{`foldl`}} but returns a list of reduced values rather than
* only the end result.
*
* @param An operator `op`
* @param An initial value `r`
* @param A list `xs = [e0, e1, e2, ...]`
* @result `[r, op r e0, op (op r e0) e1, ...]`
*/
scan :: (a -> .(.b -> a)) a ![.b] -> .[a]
// On Booleans
and :: ![.Bool] -> Bool // e0 && e1 ... && e##
or :: ![.Bool] -> Bool // e0 || e1 ... || e##
any :: (.a -> .Bool) ![.a] -> Bool // True, if ei is True for some i
all :: (.a -> .Bool) ![.a] -> Bool // True, if ei is True for all i
//* Check that all booleans are {{`True`}}. Also see {{`all`}}.
and :: ![.Bool] -> Bool
//* Check that at least one boolean is {{`True`}}. Also see {{`any`}}.
or :: ![.Bool] -> Bool
//* Check that a predicate holds for at least one list element.
any :: (.a -> .Bool) ![.a] -> Bool
//* Check that a predicate holds for all list elements.
all :: (.a -> .Bool) ![.a] -> Bool
// When equality is defined on list elements
isMember :: a !.[a] -> Bool | Eq a // Is element in list
//* Check if an element is in the list.
isMember :: a !.[a] -> Bool | Eq a
special a=Int
a=Char
a=Real
isAnyMember :: !.[a] !.[a] -> Bool | Eq a // Is one of arg1 an element arg2
//* Check that the intersection between two lists is not empty.
isAnyMember :: !.[a] !.[a] -> Bool | Eq a
special a=Int
a=Char
a=Real
removeMember :: a !u:[a] -> u:[a] | Eq a // Remove first occurrence of arg1 from list arg2
//* Remove the first occurrence of an element from the list.
removeMember :: a !u:[a] -> u:[a] | Eq a
special a=Int
a=Char
a=Real
removeMembers :: !u:[a] !.[a] -> u:[a] | Eq a // Remove first occurrences in arg2 from list arg1
/**
* Remove the first occurrences of the elements of the second list from the
* first list.
*/
removeMembers :: !u:[a] !.[a] -> u:[a] | Eq a
special a=Int
a=Char
a=Real
removeDup :: !.[a] -> .[a] | Eq a // Remove all duplicates from list
//* Remove all duplicates from a list.
removeDup :: !.[a] -> .[a] | Eq a
special a=Int
a=Char
a=Real
removeIndex :: !a !u:[a] -> (Int,u:[a]) | Eq a // "removeMember" returning index of removed element
/**
* Remove the first occurrence of an element from a list.
* @result The index of the removed element
* @result The new list
*/
removeIndex :: !a !u:[a] -> (Int,u:[a]) | Eq a
special a=Int
a=Char
a=Real
limit :: !.[a] -> a | Eq a // find two succeeding elements that are equal
// e.g. limit [1,3,2,2,1] == 2
/**
* Find the first element for which the next element is the same.
* E.g., `limit [1,3,2,2,1,...] = 2`
*/
limit :: !.[a] -> a | Eq a
special a=Int
a=Char
a=Real
// When addition is defined on list elements
sum :: !.[a] -> a | + , zero a // sum of list elements, sum [] = zero
//* Overloaded sum on a list. The sum of `[]` is {{`zero`}}.
sum :: !.[a] -> a | + , zero a
special a=Int
a=Real
// When multiplication and addition is defined on list elements
prod :: !.[a] -> a | * , one a // product of list elements, prod [] = one
//* Overloaded product of a list. The product of `[]` is {{`one`}}.
prod :: !.[a] -> a | * , one a
special a=Int
a=Real
avg :: !.[a] -> a | / , IncDec a // average of list elements, avg [] gives error!
//* Overloaded average of a list. The average of `[]` gives a runtime error.
avg :: !.[a] -> a | / , IncDec a
special a=Int
a=Real
......
......@@ -6,31 +6,43 @@ definition module StdMaybe
from StdOverloaded import class ==(..);
/**
* The Maybe type represents an optional value by providing a constructor
* for no value (`Nothing`) and a constructor for just a value (`Just`).
*/
:: Maybe x
= Just x
| Nothing
isJust :: !(Maybe .x) -> Bool // case @1 of (Just _) -> True; _ -> False
isNothing :: !(Maybe .x) -> Bool // not o isJust
fromJust :: !(Maybe .x) -> .x // \(Just x) -> x
//* `case @1 of ({{Just}} _) -> True; _ -> False`
isJust :: !(Maybe .x) -> Bool
// for possibly unique elements:
//* `{{not}} {{o}} {{isJust}}`
isNothing :: !(Maybe .x) -> Bool
//* `\({{Just}} x) -> x`
fromJust :: !(Maybe .x) -> .x
//* {{`isJust`}} for a possibly unique value.
isJustU :: !u:(Maybe .x) -> (!Bool, !u:Maybe .x)
//* {{`isNothing`}} for a possibly unique value.
isNothingU :: !u:(Maybe .x) -> (!Bool, !u:Maybe .x)
//* Apply a function on the value boxed in {{`Just`}}, or pass on {{`Nothing`}}.
mapMaybe :: .(.x -> .y) !(Maybe .x) -> Maybe .y
// mapMaybe f (Just x) = Just (f x)
// mapMaybe f Nothing = Nothing
instance == (Maybe x) | == x
// Nothing==Nothing
// Just a ==Just b <= a==b
/**
* @result A list with no or one element.
*/
maybeToList :: !(Maybe .a) -> [.a];
// returns list with no or one element
/**
* @result {{`Just`}} the head of the list or {{`Nothing`}} if it is empty.
*/
listToMaybe :: ![.a] -> .Maybe .a;
// returns Just head of list if possible
//* `catMaybes ms = [m \\ {{Just}} m <- ms]`
catMaybes :: ![Maybe .a] -> .[.a];
// catMaybes ms = [ m \\ Just m <- ms ]
system module StdMisc
/**
* Miscellaneous functions.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 3.0
// Copyright 2019 University of Nijmegen
// ****************************************************************************************
/**
* Print a message and abort the program.
*
* @param The message to print
* @result There is no result; the program will terminate
*/
abort :: !{#Char} -> .a :== code { .d 1 0 ; jsr print_string_ ; .o 0 0 ; halt }
// stop reduction and print argument
undef :: .a // fatal error, stop reduction.
/**
* The undefined value.
*
* @result An attempt to evaluate the result will yield a runtime error.
*/
undef :: .a
definition module StdOrdList
/**
* Functions to work with lists of elements for which an ordering exists.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 2.0
// Copyright 1998 University of Nijmegen
......@@ -7,29 +11,53 @@ definition module StdOrdList
import StdClass
sort :: !u:[a] -> u:[a] | Ord a // Sort the list (mergesort)
//* Sort a list (mergesort).
sort :: !u:[a] -> u:[a] | Ord a
special
a = Char
a = Int
a = Real
sortBy :: (a a -> Bool) !u:[a] -> u:[a] // Sort the list, arg1 is < function
merge :: !u:[a] !v:[a] -> w:[a]
| Ord a,[u v <= w] // Merge two sorted lists giving a sorted list
/**
* Sort a list using a custom ordering.
* @param The custom {{`<`}} function
*/
sortBy :: (a a -> Bool) !u:[a] -> u:[a]
//* Merge two sorted lists.
merge :: !u:[a] !v:[a] -> w:[a] | Ord a,[u v <= w]
special
a = Char
a = Int
a = Real
mergeBy :: (a a -> Bool) !u:[a] !v:[a] -> w:[a] // Merge two sorted lists giving a sorted list
,[u v <= w] // arg1 is < function
maxList :: !.[a] -> a | Ord a // Maximum element of list
/**
* Merge two sorted lists using a custom ordering.
* @param The custom {{`<`}} function
*/
mergeBy :: (a a -> Bool) !u:[a] !v:[a] -> w:[a],[u v <= w]
//* The maximum element of a list.
maxList :: !.[a] -> a | Ord a
special
a = Char
a = Int
a = Real
maxListBy :: (a a -> Bool) !.[a] -> a // Maximum element of list, arg1 is < function
minList :: !.[a] -> a | Ord a // Minimum element of list
/**
* The maximum element of a list using a custom ordering.
* @param The custom {{`<`}} function
*/
maxListBy :: (a a -> Bool) !.[a] -> a
//* The minimum element of a list.
minList :: !.[a] -> a | Ord a
special
a = Char
a = Int
a = Real
minListBy :: (a a -> Bool) !.[a] -> a // Minimum element of list, arg1 is < function
/**
* The minimum element of a list using a custom ordering.
* @param The custom {{`<`}} function
*/
minListBy :: (a a -> Bool) !.[a] -> a
definition module StdOverloaded
/**
* A number of common overloaded functions.
*/
// ****************************************************************************************
// Concurrent Clean Standard Library Module Version 2.0
// Copyright 1998 University of Nijmegen
// ****************************************************************************************
class (+) infixl 6 a :: !a !a -> a // Add arg1 to arg2
//* Add `arg1` to `arg2`.
class (+) infixl 6 a :: !a !a -> a
//* Subtract `arg2` from `arg1`.
class (-) infixl 6 a :: !a !a -> a
//* Zero (unit element for addition).
class zero a :: a
//* Multiply `arg1` with `arg2`.
class (*) infixl 7 a :: !a !a -> a
//* Divide `arg1` by `arg2`.
class (/) infixl 7 a :: !a !a -> a
//* One (unit element for multiplication).
class one a :: a
//* True if `arg1` is equal to `arg2`.
class (==) infix 4 a :: !a !a -> Bool
//* True if `arg1` is less than `arg2`.
class (<) infix 4 a :: !a !a -> Bool
//* True if `arg1` is an even number.
class isEven a :: !a -> Bool;
//* True if `arg1` is an odd number.
class isOdd a :: !a -> Bool;
/**