-- «•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»«•»
-- Making the license a package comment causes it to be part of every
-- runnable frege code.
{--
Copyright © 2011, Ingo Wechsung
All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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. Neither the name of the copyright holder
nor the names of its contributors may be used to endorse or
promote products derived from this software without specific
prior written permission.
*THIS SOFTWARE IS PROVIDED BY THE
COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER
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.*
-}
{--
*
* This package provides basic definitions for the Frege language.
*
* The _Prelude_ packages are imported explicitly or implicetly during compilation
* of any other package.
* They define basic data structures, classes and functions.
*
* The types and constructors for lists, unit type and tuple types are not
* defined here: They are provided programmaticaly by the compiler when it
* compiles a package with the name @frege.prelude.PreludeBase@. Nevertheless, they are
* considered part of the _Prelude_, thus qualified names like '(,)'
* are okay.
*
* The packages are _implementation specific_ insofar as the compiler may
* assume that certain items are defined here in a certain way.
* Changes may thus lead
* to compiler crashes or java code that will be rejected by the java compiler.
-}
{-
Overview of the type class hierarchy
> Eq equality, provides relational operators '==' and '!='
> Ord ordering, provides relational operators '<' '<=' '>' '>=' and '<=>'
> Enum enumarations (succ, pred, etc.)
> Num numbers
> Real real numbers
> Integral integral numbers
> Show string representation of values
> Length data types that have a length
> Empty data types that have an empty value
> AbstractList data types that behave like lists
-}
{-
Uncommon characters defined here:
> Char used for howto type in editor
> • function composition ALT+0149 CTRL+.
> « left shift? ALT+0171 CTRL+<
> » right shift? ALT+0187 CTRL+Shift+<
> ¦ to be determined ALT+0166 Alt+Shift+<
> ¿ to be determined ALT+0191 CTRL+ß (?)
> ´ regular expressions ALT+0180
>
-}
protected package frege.prelude.PreludeBase
inline candidates (otherwise, id, const, asTypeOf, $!, $, •, <~, flip, ST.>>=,
State.put, State.change, State.>>=, State.>>, State.return, State.run)
where
{-
* $Author$
* $Revision$
* $Id$
* $Date$
-}
{-
* Here are the standard operators in precedence order
* (higher numbers mean more tight binding)
* This is so that @!x@ can be thought of having
* precedence 18 and @(f x)@ can be tought of as having precedence 17
-}
infixr 16 `<~` `•` -- a <~ (b <~ c) == (c ~> b) ~> a
infixl 16 `!!` `~>`
infixr 15 `**` `??` -- `^`
infix 15 `=~` `!~` `?~` `/~` `~` `~~` `~~~`
infixl 14 `*` `/` `%` `mod` `rem` `div` `quot`
infix 14 `\\`
infixl 13 `+` -- `-` is handled specially
infixr 13 `++` mplus
infixl 12 `<<` `bshl` `bshr` `ushr`
infixl 11 `band`
infixl 10 `bor` `bxor`
infix 9 `<=` `>=` `<` `>` `elem` `notElem`
infix 8 `<=>` `compare`
infix 7 `==` `!=` `/=` `===` `!==` -- `<>`
infixr 6 `&&` `und`
infixr 5 `||` `oder` `^^`
infix 4 `..`
infixr 4 `:`
infixl 4 `<$>` `<*>` `<*` `*>` fmap
infixl 3 `>>` `>>=` -- monad bind
infixr 3 `<=<` `>=>` -- Kleisli opeartors
infixr 2 `:=` `=<<` `@` `seq` -- so that in x@a:bs x is bound to the list
infixr 1 `$` `$!`
--------------------------------------------------------------------------------
-- CLASS SECTION
--------------------------------------------------------------------------------
{-- The class 'Eq' provides operators '==', '!=' and 'hashCode'.
All types whose values can be compared for equality should be instances of
this class. For algebraic data types instances can be automatically derived
if all components are themselves instances of 'Eq'.
-}
class Eq eq where
--- Check for equality. This function is required in all instances.
--- Ayn Rand's favorite law
--- > a == a
--- shall be obeyed by all implementations.
(==), (/=) :: eq -> eq -> Bool -- must be defined in instances
--- Check for inequality. The default implementation obeys the laws
--- > !(a != a)
--- > (a != b) == !(a == b)
--- > (a == b) != (a != b)
--- These laws shall also be obeyed in all implementations.
(!=) :: eq -> eq -> Bool
a!=b = if a==b then false else true -- may be replaced by more efficient version
--- provided for Haskell compatibility as an alias for '!='
(/=) = (!=)
--- Compute a hash code.
--- The follwoing rules shall hold in all instances:
--- > a == b ==> hashCode a == hashCode b
--- > hashCode a != hashCode b ==> a != b
--- In addition, unequal values should produce unequal hashcodes more likely than not.
hashCode :: eq -> Int
instance Eq Bool where
pure native == :: Bool -> Bool -> Bool
pure native != :: Bool -> Bool -> Bool
hashCode true = 1
hashCode false = 0
{--
* Determines the constructor of a value.
* This is used like
* >constructor arg
* where @arg@ is any frege value.
*
* Returns 0 for product types and native types or
* the /constructor number/ for constructed types. The /constructor number/
* is a small integer stored in every constructed value. It indicates by
* what data constructor a value was constructed.
*
* The compiler assigns constructor numbers starting from 0 to the constructors
* defined in a @data@ definition in the order of their appearance.
*
* Examples
* >constructor [] == 0
* >constructor (a:as) == 1
* >constructor "string" == 0 // native value
*
* This function is strict in its argument, i.e.
* >constructor undefined == undefined
*
* *Implementation specific:* This function is used in derived instances
* of 'Eq' and 'Ord'.
-}
pure native constructor "frege.RT.constructor" :: a -> Int;
-- ######## Java Boxed Types ####################
-- data JBoolean = native java.lang.Boolean
-- data JByte = native java.lang.Byte
-- data JChar = native java.lang.Character
-- data JShort = native java.lang.Short
-- data JInteger = native java.lang.Integer
-- data JLong = native java.lang.Long
-- data JFloat = native java.lang.Float
-- data JDouble = native java.lang.Double
--######### Basic types ####################
{--
'Bool' values are based on Java's primitive @boolean@ values.
Note that @true@ and @false@ are literals, not constructors.
-}
data Bool = native boolean
{--
This is a constant with the value @true@.
It is most often used as the last alternative in pattern guards:
> foo n | n >= 0 = ...
> | otherwise = ...
-}
otherwise = true
{--
This is used by code generation when a conditional expression
appears in a lazy context, i.e.
> (42, if foo then bar else baz)
@lazyif a b c@ evaluates to @b@ if @a@ is @true@, otherwise to @c@.
-}
lazyif a b c = if a then b else c
{--
'Int' values are based on Java's primitive @int@ values.
The existence of this type is assumed in numerous places in the compiler.
Like with all @native@ Java types, be they primitive or reference types,
Frege holds the raw @int@ in boxed form. However, in certain cases the
compiler will optimize the boxing away:
- Strict variables or function arguments work with the unboxed value directly.
- Functions with a @native@ return type generally return the unboxed value.
Polymorphic data structures or functions always work with boxed values.
Thus, for example, the function
> sum a b c = a + b + c
can compute the sum of 3 'Int's, 'Long's, 'Double's or any other values
of a type that is an instance of type class 'Num', but it may be somewhat
slower than functions spezialized for a given type.
According to the Java Language Specification, @int@ values are
32 bit wide signed two's complement integers (§4.2). Java operations on @int@ do
not indicate overflow or underflow in any way (§4.2.2). Instead, just the low 32 bits of
every result are retained.
-}
data Int = native int where
--- convert an 'Int' to a 'Float', i.e. @2.float == 2.0f@.
--- For large integers, the result may have been be rounded.
pure native float java.lang.Float.valueOf :: Int -> Float
--- convert an 'Int' to a 'Double', i.e. @2.double == 2.0@.
pure native double java.lang.Double.valueOf :: Int -> Double
--- Convert an 'Int' to a 'Long', i.e. @2.long == 2L@.
pure native long java.lang.Long.valueOf :: Int -> Long
--- @i.char@ returns the 'Char' value whose ordinal number is @i@
--- Result is only valid for integers in the range 0..65535
pure native char "(char)" :: Int -> Char
--- Computes binary /or/ of two integers. Uses the java @|@-operator.
pure native bor "|" :: Int -> Int -> Int
--- Computes binary /exclusive or/ of two integers. Uses the java @^@-operator.
pure native bxor "^" :: Int -> Int -> Int
--- Computes binary /and/ of two integers. Uses the java @&@-operator.
pure native band "&" :: Int -> Int -> Int
-- Compare 2 intergers, use java operator
-- pure native (==) :: Int -> Int -> Bool // is defined in Eq
--- convert to a hexadecimal string
pure native toHexString java.lang.Integer.toHexString :: Int -> String
--- The 'hashCode' of an 'Int' is the identity
hashCode i = i
{--
* 'Integer' is
* a type for integer numbers of unlimited size,
* It has instances for 'Eq', 'Ord', 'Show' and 'Integral'.
* This is derived from @java.math.BigInteger@.
-}
data Integer = native java.math.BigInteger where
-- constants
pure native zero java.math.BigInteger.ZERO :: Integer
pure native one java.math.BigInteger.ONE :: Integer
pure native ten java.math.BigInteger.TEN :: Integer
--- construction from a 'Long', see also 'String.aton' and 'String.integer'
pure native valueOf java.math.BigInteger.valueOf :: Long -> Integer
-- arithmetic operations
pure native + add :: Integer -> Integer -> Integer
pure native * multiply :: Integer -> Integer -> Integer
pure native - subtract :: Integer -> Integer -> Integer
pure native quot divide :: Integer -> Integer -> Integer
pure native rem remainder :: Integer -> Integer -> Integer
--- /Warning/! Throws @ArithmeticException@ when divisor is negative.
pure native nMod mod :: Integer -> Integer -> Integer
pure native abs :: Integer -> Integer
pure native negate :: Integer -> Integer
-- relational
pure native compareTo :: Integer -> Integer -> Int
pure native max :: Integer -> Integer -> Integer
pure native min :: Integer -> Integer -> Integer
-- shift
pure native bshr shiftRight :: Integer -> Int -> Integer
pure native bshl shiftLeft :: Integer -> Int -> Integer
--- unsigned right shift on big integers does not really make sense ...
b `ushr` i = abs b `bshr` i
-- bit arithmetic
pure native bor or :: Integer -> Integer -> Integer
pure native band and :: Integer -> Integer -> Integer
pure native bxor xor :: Integer -> Integer -> Integer
pure native bcmpl not :: Integer -> Integer
-- miscellanous
pure native bitLength :: Integer -> Int
pure native toString :: Integer -> String
pure native sign signum :: Integer -> Int
pure native long longValue :: Integer -> Long
pure native int intValue :: Integer -> Int
pure native hashCode :: Integer -> Int
pure native gcd :: Integer -> Integer -> Integer
{--
* 'Long' values are based on Java's primitive @long@ values.
*
* According to the Java Language Specification, @long@ values are
64 bit wide signed two's complement integers (§4.2). Java operations on @long@ do
not indicate overflow or underflow in any way (§4.2.2). Instead, just the low 64 bits of
every result are retained.
-}
data Long = native long where
--- Convert an 'Long' to a 'Float', i.e. @42L.float == 42.0f@.
--- For large numbers, the result may have been be rounded.
pure native float java.lang.Float.valueOf :: Long -> Float
--- Convert an 'Long' to a 'Double', i.e. @42L.double == 42.0@.
--- For large numbers, the result may have been be rounded.
pure native double java.lang.Double.valueOf :: Long -> Double
--- Uses a java cast to convert a 'Long' to an 'Int'. This is a /narrowing primitive conversion/ in java parlance.
pure native int "(int)" :: Long -> Int
--- Computes binary /or/ of two long integers. Uses the java @|@-operator.
pure native bor "|" :: Long -> Long -> Long
--- Computes binary /exclusive or/ of two long integers. Uses the java @^@-operator.
pure native bxor "^" :: Long -> Long -> Long
--- Computes binary /and/ of two integers. Uses the java @&@-operator.
pure native band "&" :: Long -> Long -> Long
--- hash code is upper half and lower half xor'ed
hashCode l = (int l).bxor (int (l `bshr` 32))
--- 'Char' values are based on Java's primitive @char@ values.
data Char = native char where
{--
* @c.ord@ is the ordinal (integer) value of the character @c@.
* It holds: @c.ord.char@ == @c@, see 'Int.char'.
* (But note that @i.char.ord@ is not necessarily @i@)
-}
pure native ord "(int)" :: Char -> Int
pure native hashCode "(int)" :: Char -> Int
pure native isLowerCase java.lang.Character.isLowerCase :: Char -> Bool
pure native toLowerCase java.lang.Character.toLowerCase :: Char -> Char
pure native isUpperCase java.lang.Character.isUpperCase :: Char -> Bool
pure native toUpperCase java.lang.Character.toUpperCase :: Char -> Char
pure native isWhitespace java.lang.Character.isWhitespace :: Char -> Bool
pure native isLetterOrDigit java.lang.Character.isLetterOrDigit :: Char -> Bool
{--
'String' values are based on Java's @java.lang.String@ objects.
'String' is an alias for 'StringJ' 'Char'
-}
type String = StringJ Char
{--
For technical reasons, the native string type is defined with a phantom type,
which allows us to treat strings like character lists.
The following rules apply:
- There must be no polymorphic non empty string. Trying to extract elements from it
with 'itemAt' would fail with an exception at runtime.
- Every function with return type ('StringJ' a) must either take one or more arguments
of the same type which it manipulates, or it must return the empty string. In the former
case, the elements of the result string must all be computed from the
elements of the argument strings.
-}
protected data StringJ a = native java.lang.String where
--- The length of a 'String'
pure native length :: StringJ a -> Int
--- Polymorphic variant of 'elemAt'
--- Always returns a character (what else?) for nonempty strings.
pure native itemAt frege.RT.itemAt :: StringJ a -> Int -> a
{-- Like 'String.int', but the exception is not checked, thus only good when one *knows for sure* that the parse will succeed. -}
pure native atoi java.lang.Integer.parseInt :: String -> Int
{-- Like 'String.long', but the exception is not checked, thus only good when one *knows for sure* that the parse will succeed. -}
pure native atol java.lang.Long.parseLong :: String -> Long
{-- Like 'String.float', but the exception is not checked, thus only good when one *knows for sure* that the parse will succeed. -}
pure native atof java.lang.Float.parseFloat :: String -> Float
{-- Like 'String.double', but the exception is not checked, thus only good when one *knows for sure* that the parse will succeed. -}
pure native atod java.lang.Double.parseDouble :: String -> Double
{-- Like 'String.integer', but the exception is not checked, thus only good when one *knows for sure* that the parse will succeed. -}
pure native aton new :: String -> Integer
{-- Safe way to parse an integer from a string.
@java.lang.NumberFormatException@ will be catched and returned as 'Left' value.
When the parse succeeds, the integer is returned in the 'Right' value.
Use like this:
> case s.int of
> Left exc -> ... // s is not well formed
> Right i -> ... // the parsed value is in i
-}
pure native int java.lang.Integer.parseInt :: String -> Exception Int
--- Safe way to parse a long integer from a string. See 'String.int'
pure native long java.lang.Long.parseLong :: String -> Exception Long
--- Safe way to parse a 'Float' value from a string. See 'String.int'
pure native float java.lang.Float.parseFloat :: String -> Exception Float
--- Safe way to parse a 'Double' value from a string. See 'String.int'
pure native double java.lang.Double.parseDouble :: String -> Exception Double
--- Safe way to parse a big 'Integer' value from a string. See 'String.int'
pure native integer new :: String -> Exception Integer
--- retrieve character at index
pure native charAt :: String -> Int -> Char
--- Get character at index.
--- This will allow to use a string like an array, e.g. @"xyz".[1]@
pure native frozenGetAt charAt :: String -> Int -> Char
pure native elemAt charAt :: String -> Int -> Char
--- interpret this string as regex (unsafe, does not catch exceptions)
--- see 'regcomp' for an alternative
pure native compile java.util.regex.Pattern.compile :: String -> Regex
--- quote regular expression metacharacters in string
pure native quote java.util.regex.Pattern.quote :: String -> String
--- quote replacement string metacharacters in string
pure native quoteReplacement java.util.regex.Matcher.quoteReplacement
:: String -> String
--- convert to lower case
pure native toLowerCase :: String -> String
--- convert to upper case
pure native toUpperCase :: String -> String
--- 'String.compareTo' is used in the 'Ord' instance of 'String'
pure native compareTo :: String -> String -> Int
--- Concatenate two strings, uses Java's @+@ operator
pure native ++ + :: StringJ a -> StringJ a -> StringJ a -- String concatenation
--- get the has code
pure native hashCode :: String -> Int
{--
@substr s start end@ returns the sub string of @s@ that starts
with the character at position @start@
and extends to the character at position @end-1@.
This uses the native method @substring@ of class @java.lang.String@. It
will throw an @IndexOutOfBoundsException@ if @start@ is negative or larger than
@end@ or if @end@ is greater than the length of @s@.
-}
pure native substr substring :: StringJ a -> Int -> Int -> StringJ a
{--
@strtail s n@ returns a new string that is a substring of string _s_.
The substring begins with the character at the specified index
and extends to the end of _s_.
This uses the native method @substring@ of class @java.lang.String@. It
will throw an @IndexOutOfBoundsException@ if _n_ is negative or larger than
the length of _s_.
-}
pure native strtail substring :: StringJ a -> Int -> StringJ a
--- compile a 'String' to a 'Regex'
pure native regcomp java.util.regex.Pattern.compile :: String -> Exception Regex
atoi (s::String) = s.atoi
--- 'Float' values are based on Java's primitive @float@ values.
{--
According to the Java Language Specification §4.2.3, @float@ values are
32-bit-precision binary floating point values. The values and the operations
on it behave as speicified in the IEEE Standard for Binary Floating-Point Arithmetic.
-}
data Float = native float where
{--
Returns the closest 'Int' value to the argument.
The result is rounded to an integer by adding 1/2,
taking the 'Float.floor' of the result,
and casting the result to type int.
The following property holds:
> (f < Int.maxBound.float && f > Int.minBound.float) ==>
> (f.int.float == (f + 0.5f).floor)
Special cases:
- If the argument is NaN, the result is 0.
- If the argument is negative infinity or any value less than or equal
to the value of 'Int.minBound', the result is equal to the value of
'Int.minBound'.
- If the argument is positive infinity or any value greater than or equal
to the value of 'Int.maxBound', the result is equal to the value of
'Int.maxBound'.
-}
pure native int java.lang.Math.round :: Float -> Int
{--
Returns the largest (closest to positive infinity) value that is
less than or equal to the argument and is equal to a mathematical integer.
Special cases:
- If the argument value is already equal to a mathematical integer,
then the result is the same as the argument.
- If the argument is NaN or an infinity or positive zero or
negative zero, then the result is the same as the argument.
-}
floor f = (Float.double f).floor.float
--- Applies the java widening primitive conversion from @float@ to @double@.
pure native double "(double)" :: Float -> Double
--- bit representation of a float serves as hashCode
pure native hashCode java.lang.Float.floatToIntBits :: Float -> Int
--- 'Double' values are Java's primitive @double@ values.
{--
According to the Java Language Specification §4.2.3, @double@ values are
64-bit-precision binary floating point values. The values and the operations
on it behave as speicified in the IEEE Standard for Binary Floating-Point Arithmetic.
-}
data Double = native double where
{--
Returns the closest 'Long' value to the argument.
The result is rounded to an integer by adding 1/2,
taking the 'Double.floor' of the result,
and casting the result to type @long@.
The following property holds:
> (d < Long.maxBound.double && d > Long.minBound.double) ==>
> (d.long.double == (d + 0.5d).floor)
Special cases:
- If the argument is NaN, the result is 0.
- If the argument is negative infinity or any value less than or equal
to the value of 'Long.minBound', the result is equal to the value of
'Long.minBound'.
- If the argument is positive infinity or any value greater than or equal
to the value of 'Long.maxBound', the result is equal to the value of
'Long.maxBound'.
-}
pure native long java.lang.Math.round :: Double -> Long
{--
Returns the largest (closest to positive infinity) value that is
less than or equal to the argument and is equal to a mathematical integer.
Special cases:
- If the argument value is already equal to a mathematical integer,
then the result is the same as the argument.
- If the argument is NaN or an infinity or positive zero or
negative zero, then the result is the same as the argument.
-}
pure native floor java.lang.Math.floor :: Double -> Double
--- Applies the java narrowing primitive conversion from @double@ to @float@
pure native float "(float)" :: Double -> Float
--- bit representation of a double
pure native longBits java.lang.Double.doubleToLongBits :: Double -> Long
--- the 'hashCode' is that of the 'Long' value used to represent the 'Double'
hashCode d = (longBits d).hashCode
{--
* 'Regex' values are based on Java's @java.util.regex.Pattern@ objects.
* All regular expression literals are values of this type.
-}
data Regex = native java.util.regex.Pattern where
pure native pattern :: Regex -> String
--- create a 'Matcher' from a regular expression and a 'String'
pure native matcher :: Regex -> String -> Matcher
-- the following have been moved to Arrays
-- pure native split :: Regex -> String -> StringArr
{-
Split a string around matches of a regular expression and return
the result as list of strings.
-}
-- splitted r s = (split r s).toList
{--
'Matcher' values are based on Java's @java.util.regex.Matcher@ objects.
Code generation relies on the existence of this type and its operations.
The native 'Matcher' functions that correspond to java methods
of the @java.util.regex.Matcher@ class that modify the state of the
object they are invoked on
('Matcher.find', 'Matcher.matches', 'Matcher.replaceFirst', 'Matcher.replaceAll',
'Matcher.usePattern', 'Matcher.useAnchoringBounds') are implemented
so that they make a copy of the 'Matcher' and invoke the impure java method
on the copy.
Frege 'Matcher's can thus be regarded as read-only values and
the functions defined here as pure. If you need to pass a 'Matcher' to
other native functions, be sure that the function is pure. If it is not
because it would modify the matcher, and you do not need the match result, always
pass a clone of the Matcher (see 'Matcher.clone')
-}
data Matcher = pure native java.util.regex.Matcher where
pure native clone frege.RT.clone :: Matcher -> Matcher
{-- Tries a match and if it succeeds, returns @Just m@, where @m@ is
* a new 'Matcher' that contains the result. If there is no match, @Nothing@
* is returned.
*
* The following java fragment appends all matched substrings of a string:
* > String s = "cats and dogs are not concatenated.";
* > Pattern p = Pattern.compile("cat|dog");
* > String result = "";
* > Matcher m = p.matcher(s);
* > while (m.find()) result += m.group(0); // "catdogcat"
* The follwoing frege fragment computes the same result:
> result = loop m "" where
> s = "cats and dogs are not concatenated."
> p = #cat|dog#
> m = p.matcher s
> loop :: Matcher -> String -> String
> loop m1 r | Just m2 <- m1.find = loop m2 (r++m2.match)
> | otherwise = r
-}
pure native find frege.RT.find :: Matcher -> Maybe Matcher
--- Tries to match the entire string and returns @Just m@ on success and otherwise @Nothing@.
pure native matches frege.RT.matches :: Matcher -> Maybe Matcher
{--
Retrieves the input subsequence captured by the given group
during the previous match operation.
Capturing groups are indexed from left to right, starting at one.
Group zero denotes the entire pattern, so the expression @(m.group 0)@
retrieves that portion of the input string that was matched by the pattern.
If the match was successful but the group specified failed to match any
part of the input sequence, then 'Nothing' is returned. Note that some
groups, for example @(a?)@, match the empty string.
This functon will return @Just ""@ when such a group successfully
matches the empty string in the input.
The folloing property holds for a 'Matcher' /m/ with input
sequence /s/ and group index /g/:
> isJust (m.group g) ==> (m.group g) == Just (s.substr (m.start g) (m.end g))
-}
pure native group :: Matcher -> Int -> (Maybe String)
{--
@Matcher.match m@ returns the input subsequence matched by the previous match.
The result is 'undefined' if the last match was not successful.
For a 'Matcher' @m@ with input sequence @s@, the following holds:
> isJust (m.group 0) ==> unJust (m.group 0) == m.match
Note that some patterns, for example @a?@, match the empty string.
This method will return the empty string when the pattern successfully
matches the empty string in the input.
-}
pure native match group :: Matcher -> String
{--
Returns the start index of the subsequence captured by the
given group during the previous match operation where group 0 denotes
the entire pattern.
If the specified capturing group failed to match,
the return value will be -1.
The follwoing property holds:
> (m.group n == Nothing) ==> (m.start n < 0)
-}
pure native start :: Matcher -> Int -> Int
{--
Returns the offset after the last character of the subsequence
captured by the
given group during the previous match operation where group 0 denotes
the entire pattern.
If the specified capturing group failed to match,
the return value will be -1.
The follwoing property holds:
> (m.group n == Nothing) ==> (m.end n < 0)
-}
pure native end :: Matcher -> Int -> Int
{--
Makes a new 'Matcher' and causes it to use a different 'Regex' for future matches.
The original matchers position in the input and its
last append position is copied, but information about the last match, if any,
is not.
This is most useful with patterns that start with the @\\G@ anchor.
Note that, due to a java bug, if the last find operation matched the empty string,
the next find will fail. For a workaround see 'Matcher.usePatternAndFind'
-}
pure native usePattern frege.RT.usePattern :: Matcher -> Regex -> Matcher
{--
Makes a new 'Matcher' with a different 'Regex' and tries to find a match.
If the last find on the original Matcher returned an empty result, it
calls @mnew.find(morig.end(0))@ to work around a bug in the java API.
Therefore, this function must only be used on a matcher whose last match
attempt was successful.
-}
pure native usePatternAndFind frege.RT.usePatternAndFind :: Matcher -> Regex -> Maybe Matcher
--- Requires or forbids the matcher to acknowledge anchors.
pure native useAnchoringBounds frege.RT.useAnchoringBounds :: Matcher -> Bool -> Matcher
{--
Returns the string representation of this matcher.
The string representation of a 'Matcher' contains information
that may be useful for debugging. The exact format is unspecified.
-}
pure native toString :: Matcher -> String
{--
Replaces the first subsequence of the input sequence that matches
the pattern with the given replacement string.
This method scans the input sequence from the start
looking for a match of the pattern.
Characters that are not part of the match are appended directly
to the result string; the match is replaced in the result by the
replacement string. The replacement string may contain references
to captured subsequences.
Note that backslashes (\\) and dollar signs ($) in the replacement
string may cause the results to be different than if it were
being treated as a literal replacement string.
Dollar signs may be treated as references to captured subsequences
as described above, and backslashes are used to escape
literal characters in the replacement string.
Given the regular expression @#dog#@, the input @"zzzdogzzzdogzzz"@,
and the replacement string @"cat"@, an invocation of this function
on a matcher for that expression would yield the string
@"zzzcatzzzdogzzz"@.
-}
pure native replaceFirst frege.RT.replaceFirst :: Matcher -> String -> String
--- Like 'Matcher.replaceFirst', but replaces all matches.
pure native replaceAll frege.RT.replaceAll :: Matcher -> String -> String
{--
* This is the principal return type for java methods that are expected to
* throw exceptions.
-}
type Exception a = Either JException a
{--
* We need to do some reflection from frege code.
* For example, when we catch an 'JException' thrown from Java code.
* we might want to know what it is.
-}
data Class = pure native java.lang.Class where
pure native getName :: Class -> String
pure native forName java.lang.Class.forName :: String -> Exception Class
--- Frege wrapper for java exceptions.
data JException = pure native java.lang.Exception where
pure native getLocalizedMessage :: JException -> String
pure native getMessage :: JException -> String
pure native getClass :: JException -> Class
--- give the name of this exception
catched t = (JException.getClass t).getName
{--
* Constructs a strict tuple.
* The difference to '(,)' is that both argument values
* will be evaluated before the tuple is constructed. Thus:
* >fst (42; undefined) == undefined
* >fst (42, undefined) == 42
* *Implementation specific:* The compiler will rewrite @(a;b)@ as
* @(PreludeBase.strictTuple2 a b)@.
-}
pure native strictTuple2 PreludeBase.TTuple2.mk :: a -> b -> (a,b);
--- Constructs a strict 3-tuple. See remarks for 'strictTuple2'.
pure native strictTuple3 PreludeBase.TTuple3.mk :: a -> b -> c -> (a,b,c);
--- Constructs a strict 4-tuple. See remarks for 'strictTuple2'.
pure native strictTuple4 PreludeBase.TTuple4.mk :: a -> b -> c -> d -> (a,b,c,d);
--- Constructs a strict 5-tuple. See remarks for 'strictTuple2'.
pure native strictTuple5 PreludeBase.TTuple5.mk :: a -> b -> c -> d -> e -> (a,b,c,d,e);
--- Constructs a strict 6-tuple. See remarks for 'strictTuple2'.
pure native strictTuple6 PreludeBase.TTuple6.mk :: a -> b -> c -> d -> e -> f -> (a,b,c,d,e,f);
--- Constructs a strict 7-tuple. See remarks for 'strictTuple2'.
pure native strictTuple7 PreludeBase.TTuple7.mk :: a -> b -> c -> d -> e -> f -> g -> (a,b,c,d,e,f,g);
--- Constructs a strict 8-tuple. See remarks for 'strictTuple2'.
pure native strictTuple8 PreludeBase.TTuple8.mk :: a -> b -> c -> d -> e -> f -> g -> h -> (a,b,c,d,e,f,g,h);
--- Constructs a strict 9-tuple. See remarks for 'strictTuple2'.
pure native strictTuple9 PreludeBase.TTuple9.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> (a,b,c,d,e,f,g,h,i);
--- Constructs a strict 10-tuple. See remarks for 'strictTuple2'.
pure native strictTuple10 PreludeBase.TTuple10.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> (a,b,c,d,e,f,g,h,i,j);
--- Constructs a strict 11-tuple. See remarks for 'strictTuple2'.
pure native strictTuple11 PreludeBase.TTuple11.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> (a,b,c,d,e,f,g,h,i,j,k);
--- Constructs a strict 12-tuple. See remarks for 'strictTuple2'.
pure native strictTuple12 PreludeBase.TTuple12.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> (a,b,c,d,e,f,g,h,i,j,k,l);
--- Constructs a strict 13-tuple. See remarks for 'strictTuple2'.
pure native strictTuple13 PreludeBase.TTuple13.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> (a,b,c,d,e,f,g,h,i,j,k,l,m);
--- Constructs a strict 14-tuple. See remarks for 'strictTuple2'.
pure native strictTuple14 PreludeBase.TTuple14.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n);
--- Constructs a strict 15-tuple. See remarks for 'strictTuple2'.
pure native strictTuple15 PreludeBase.TTuple15.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o);
--- Constructs a strict 16-tuple. See remarks for 'strictTuple2'.
pure native strictTuple16 PreludeBase.TTuple16.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p);
--- Constructs a strict 17-tuple. See remarks for 'strictTuple2'.
pure native strictTuple17 PreludeBase.TTuple17.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q);
--- Constructs a strict 18-tuple. See remarks for 'strictTuple2'.
pure native strictTuple18 PreludeBase.TTuple18.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
--- Constructs a strict 19-tuple. See remarks for 'strictTuple2'.
pure native strictTuple19 PreludeBase.TTuple19.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s);
--- Constructs a strict 20-tuple. See remarks for 'strictTuple2'.
pure native strictTuple20 PreludeBase.TTuple20.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t);
--- Constructs a strict 21-tuple. See remarks for 'strictTuple2'.
pure native strictTuple21 PreludeBase.TTuple21.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u);
--- Constructs a strict 22-tuple. See remarks for 'strictTuple2'.
pure native strictTuple22 PreludeBase.TTuple22.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v);
--- Constructs a strict 23-tuple. See remarks for 'strictTuple2'.
pure native strictTuple23 PreludeBase.TTuple23.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v -> w -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w);
--- Constructs a strict 24-tuple. See remarks for 'strictTuple2'.
pure native strictTuple24 PreludeBase.TTuple24.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v -> w -> x -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x);
--- Constructs a strict 25-tuple. See remarks for 'strictTuple2'.
pure native strictTuple25 PreludeBase.TTuple25.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v -> w -> x -> y -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y);
--- Constructs a strict 26-tuple. See remarks for 'strictTuple2'.
pure native strictTuple26 PreludeBase.TTuple26.mk :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v -> w -> x -> y -> z -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z);
{-
* @(try f x)@ is like @(f $ x)@
* but catches all exceptions that are thrown in @f@. To be used like
*
* > case try f x of
* > Left exception -> ...
* > Right result -> ...
*
* Note that 'try' is strict in both its arguments. The exceptions thrown
* when the arguments are evaluated will *not* be catched.
-}
-- pure native try "PreludeBase._dollar.w" :: (a -> b) -> a -> Exception b
--- @a `seq` b@ evaluates _a_ before it returns _b_
--- This is a right associative operator with precedence 15.
seq !a b = b;
--######### undefined things ####################
data Undefined = pure native frege.RT.Undefined where
pure native new :: String -> Undefined
--- create an 'Undefined' value from a string and a cause
pure native newSX new :: String -> JException -> Undefined
{-- create an 'Undefined' value from a 'JException'. The message
will be taken from the exception.
-}
newX :: JException -> Undefined
newX jex = newSX ((("caused by ".++ jex.getClass.getName).++ ": ").++ jex.getMessage) jex
--- Throw this 'Undefined', this will abort the computation evaluating it.
--- Actually, the return type is not correct, since it never returns.
pure native die :: Undefined -> Bool
{--
convert an 'Undefined' value to a 'JException'
This is actually a no-op, since @frege.RT.Undefined@ is a subclass
of @java.lang.Exception@. However, the type checker knows nothing about subclasses.
This function is used in the @Monad (Exception a)@.
-}
pure native toException "(java.lang.Exception)" :: Undefined -> JException
--- This is the standard undefined value.
undefined :: u
undefined = error "undefined"
--- Construct an undefined value with an informative message.
error :: String -> u
error s = if (Undefined.new s).die then error "a" else error "b"
--- Constructs an undefined value from a java exception and throws it.
throw u = if (Undefined.newX u).die then undefined else undefined
-- Get the head element of a non empty list. The head of an empty list is 'undefined'.
-- listhead (x:xs) = x
-- listhead [] = error "List.head []"
--######### boolean expr ########################
--- The Java @!@ operator on booleans
pure native ! :: Bool -> Bool -- = if b then false else true;
{-- The Java @&&@ operator on booleans. Note that since this is a
native function, the second argument appears strict to the compiler
when in fact it is lazy at the Java level.
This can lead to inconsistent results in some cases. For example, the following
program correctly prints @false@ in the first line of the output, but then aborts:
> main _ = do
> stdout << (false && undefined) << "\n"
> stdout << conj false undefined << "\n"
> where
> conj a b = a && b
Note that the very same behaviour is seen in the following java program
> public class And {
> static boolean undef() {
> if (true) throw new Error("undefined");
> return false;
> }
> static boolean conj(boolean a, boolean b) { return a&&b; }
> public static void main(String[] args) {
> System.out.println(false && undef());
> System.out.println(conj(false, undef()));
> }
> }
One could thus say that '&&' behaves exactly like the Java operator including
the fact that it cannot be replaced by a function without changing the semantics
of a program.
For an alternative see 'und'
-}
pure native && :: Bool -> Bool -> Bool
{--
The Java @||@ operator on booleans.
Note that since this is a
native function, the second argument appears strict to the compiler
when in fact it is lazy at the Java level.
This can lead to inconsistent results in cases where the wrong strictness of
the second argument propagates to arguments of the function that contains
an application of '||'. (The documentation for '&&' has an example.)
See 'oder' for an alternative
-}
pure native || :: Bool -> Bool -> Bool
{-- Like '&&', but second argument is lazy.
The @`und`@ operator has the same precedence and arity as '&&'.
The definition is
> a `und` b = if a then b else false
This should really be named _and_, but Haskell 2010 uses this already for lists.
Hence we use the german word _und_.
-}
a `und` b = if a then b else false
{-- Like '||', but second argument is lazy.
The @`oder`@ operator has the same precedence and arity as '||'.
The definition is
> a `oder` b = if a then true else b
This should really be named _or_, but Haskell 2010 uses this already for lists.
Hence we use the german word _oder_.
-}
a `oder` b = if a then true else b
{--
@not b@ is true if _b_ is false, otherwise true. Uses java's '!' operator.
-}
pure native not "!" :: Bool -> Bool
{--
* @a ^^ b@ is true if either _a_ or _b_ is true, but not both.
* > a ^^ b = if a then not b else b
-}
a ^^ b = if a then not b else b
--######### expr identity ######################
{-- This checks for object identity or equality of primitive values
using Java's @==@ operator.
It evaluates its arguments, so undefined values cannot be compared. -}
pure native === == :: a -> a -> Bool;
{-- This checks for object identity or inequality of primitive values
using Java's @!=@ operator.
It evaluates its arguments, so undefined values cannot be compared. -}
pure native !== != :: a -> a -> Bool;
--########### class Ord - compare ordered things ##################
--- The type of the result of '<=>'
data Ordering = Lt | Eq | Gt
{--
The 'Ord' class provides relational operators as well as the functions 'max' and 'min'.
The default implementation defines them all in terms of the _compare_ operator '<=>'.
Making some type an instance of 'Ord' makes it automatically an instance of 'Eq' if it
is not one already and if it has an implementation for 'hashCode'.
The operators '==' and '!=' will be defined in terms of '<=>'.
Instances of 'Ord' can be derived automatically for algebraic data types when
all elements of the type are themselves instances of 'Ord' and when the type is
an instance of 'Eq'.
-}
class Ord Eq ord => ord where
{-- This operator must be defined in all instances. It compares its operands and
returns 'Lt' if the first is lower than the second, 'Gt' if the first is
greater than the second and 'Ordering.Eq' otherwise.
The following shall be invariantly true:
> case a <=> b of { Eq -> a == b; _ -> a != b }
-}
(<=>) :: ord -> ord -> Ordering -- must be defined
compare :: ord -> ord -> Ordering
{-- Relational @<@ operator. Obeys the following laws:
> if a < b && b < c then a < c
> a < b == b > a
-}
(<) :: ord -> ord -> Bool
{-- Relational @<=@ operator. Obeys the following laws:
> if a <= b && b <= c then a <= c
> a <= b == b >= a
> a <= b == !(a > b)
-}
(<=) :: ord -> ord -> Bool
{-- Relational @>@ operator. Obeys the following laws:
> if a > b && b > c then a > c
> a > b == b < a
-}
(>) :: ord -> ord -> Bool
{-- Relational @>=@ operator. Obeys the following laws:
> if a >= b && b >= c then a >= c
> a >= b == b <= a
> a >= b == !(a < b)
-}
(>=) :: ord -> ord -> Bool
--- > max a b = if a > b then a else b
max :: ord -> ord -> ord
--- > min a b = if a < b then a else b
min :: ord -> ord -> ord
(a) < (b) = case a <=> b of { Lt -> true; _ -> false; }
(a) <= (b) = case a <=> b of { Gt -> false; _ -> true; }
(a) >= (b) = case a <=> b of { Lt -> false; _ -> true; }
(a) > (b) = case a <=> b of { Gt -> true; _ -> false; }
max a b = if a > b then a else b
min a b = if a < b then a else b
-- provided for Haskell compatibility as alias for '<=>'
compare = (<=>)
{-- This implementation for the ('==') operator is being used in instances
of 'Ord' when the instantiated type is not already an instance of 'Eq'.
-}
(a) == (b) = case a <=> b of { Eq -> true; _ -> false; }
{-- This implementation for the ('!=') operator is being used in instances
of 'Ord' when the instantiated type is not already an instance of 'Eq'.
-}
(a) != (b) = case a <=> b of { Eq -> false; _ -> true; }
--############# class Enum ############################################
{--
* Class 'Enum' defines operations on sequentially ordered types.
*
* A type that is an instance of 'Enum' is also an instance
* of 'Ord' (and, in turn, of 'Eq').
*
* Instances of 'Enum' may be derived for any enumeration type
* (types whose constructors have no fields).
* If there is no 'hashCode' provided, it will be the same as 'ord'.
-}
class Enum Ord e => e where
{-- @ord e@ returns the ordinal number associated with the value @e@. For
* enumeration types, 'ord' is the same as 'constructor', for 'Int', it is the
* identity function.
* Some types, like 'Long', cannot map all their values to 'Int', in such cases
* the result of applying 'ord' may be meaningless.
-}
ord :: e -> Int
{--
* This is the default implementation of the compare operator,
* that makes each 'Enum' type an 'Ord' type automatically.
* > a <=> b = (ord a).<=> (ord b)
-}
a <=> b = (ord a).<=> (ord b)
{--
* @T.from i@ maps the 'Int' value @i@ to a value of @T@, such that
> ord (T.from i) == i
* unless there is no value @e@ of @T@ so that @ord e == i@. In the
* latter case, the result is 'undefined'.
-}
from :: Int -> e
--- @succ e@ is the successor of @e@ or 'undefined' if there is no such successor.
succ :: e -> e
--- @pred e@ is the predecessor of @e@ or 'undefined' if there is no predecessor.
pred :: e -> e
-- pred x = from (ord x - 1)
-- succ x = from (ord x + 1)
{-- @a .. b@ is the list @[a, succ a, succ (succ a), ..., b ]@
* if @a < b@, or [a] if @a == b@ or the empty list if @a > b@.
-}
(..) :: e -> e -> [e]
(a) .. (b)
| a < b = a:(succ a). .. b
| a == b = [a]
| otherwise = []
--- default implementation for 'Eq.hashCode' is same as 'ord'
hashCode = ord
instance Eq () where
() != () = false
() == () = true
hashCode () = 42
--########### class Num - basic arithmetics ########################
{-- The 'Num' class provides the operators ('+'), ('-') and ('*') as well as
some functions that are common for all numeric types.
-}
class Num Ord n => n where
--- Computes the sum of two numbers
(+) :: n -> n -> n
--- Computes the difference of two numbers
(-) :: n -> n -> n
--- use @(subtract a)@ instead of @\\b -> b-a@ in sections
subtract :: n -> n -> n
--- Computes the product of two numbers
(*) :: n -> n -> n
--- Computes the absolute value
abs :: n -> n
--- Negates a number n such that if n is a number
--- > n + negate n == 0
negate :: n -> n
--- @sign n@ is -1 if n<0, 1 if n>0 and 0 otherwise
sign :: n -> Int
--- the number 1 in the instantiated type
one :: n
--- the number 0 in the instantiated type
zero :: n
abs n = if n < zero then zero-n else n
negate n = zero-n
subtract b a = a-b
sign n = constructor (n <=> zero) - 1
--- converts an 'Int' value to the instantiated type
fromInt :: Int -> n
{-- Floating point number types may have special values for _infinity_
and _negative infinity_. @isFinite n@ yields @true@ if @n@ is an infinite
value and @false@ in all other cases.
The default implementation always returns @false@ so that implementors of
instances for types without special values for infinity need not care.
See also 'isNumber'.
-}
isInfinite :: n -> Bool
isInfinite _ = false
{-- Floating point number types may have a special values for
_not a number_ (NaN). For example, @0d / 0d@ is NaN.
@isNaN n@ yields @true@ if @n@ is the special value that indicates that
@n@ is not a number and @false@ in all other cases.
The default implementation always returns @false@ so that implementors of
instances for types without such a special values need not care.
See also 'isNumber'.
-}
isNaN :: n -> Bool
isNaN _ = false
{-- Returns @true@ if @n@ is neither infinite (see 'isInfinite') nor NaN (see 'isNaN').
Note that certain properties for funtions on numbers are true only under the assumption
that the argument values are numbers.
The default implementation is
> isNumber n = !(isInfinite n) && !(isNaN n)
so that the function should always compute
the right answer as long as 'isInfinite' and 'isNaN' do.
-}
isNumber :: n -> Bool
isNumber n = !(isInfinite n) && !(isNaN n)
{--
* The 'Real' class provides the division operator ('/').
-}
class Real Num r => r where
--- the division operator
(/) :: r -> r -> r
{--
* 'Integer' is an instance of 'Ord'
-}
instance Ord Integer where
a <=> b = (a.compareTo b).<=> 0
a > b = (a.compareTo b).> 0
a < b = (a.compareTo b).< 0
a >= b = (a.compareTo b).>= 0
a <= b = (a.compareTo b).<= 0
a == b = (a.compareTo b).== 0
a != b = (a.compareTo b).!= 0
{--
* 'Integer' is an instance of 'Enum'
-}
instance Enum Integer where
--- @succ b@ is the same as @b + 1.big@
succ b = b + Integer.one
--- @succ b@ is the same as @b + 1.big@
pred b = b - Integer.one
--- @ord b@ is only defined if the value of b is in the range 'Int.minBound' .. 'Int.maxBound'
ord b = b.int
--- @Integer.from i@ is the same as @Int.big i@
from i = i.big
;
{--
* 'Integer' is an instance of 'Integral'
-}
instance Integral Integer where
fromInt i = Int.big i
big b = b -- i am already big
--- Class 'Integral' provides bit arithmetic, division and remainder operations for integral numbers.
class Integral Num integ => integ where
--- integer division
div, quot :: integ -> integ -> integ
--- Haskell compatibility
quotRem, divMod :: integ -> integ -> (integ, integ)
quotRem a b = (a `quot` b, a `rem` b)
divMod a b = (a `div` b, a `mod` b)
--- The remainder á la Java operator @%@ - @a `rem` b@ has same sign as @a@
--- > forAll arbitrary (\a -> forAll arbitrary (\b -> (a `quot` b) * b + (a `rem` b) = a
--- This behaviour is the same as in Haskell
rem :: integ -> integ -> integ
mod :: integ -> integ -> integ
--- This modulo operator works so that
--- > forAll arbitrary (\a -> forAll arbitrary (\b -> (a `div` b) * b + (a `mod` b) = a))
--- In addition, it is the case that
--- > forAll arbitrary (\a -> forAll arbitrary (\b -> @(a `quot` b) == (a `div` b) || (a `quot` b) == (a `div` b)-1))
a `mod` b = case a `rem` b of
r | r == zero = r
| (a >= zero) == (b >= zero) = r -- a and b have same sign
| otherwise = r + b
a `div` b = case a `quot` b of
q | (a >= zero) == (b >= zero) = q -- a and b have same sign
| q * b == a = q
| otherwise = q-one
--- binary and, supposed to work like Java @&@ on all integral types
band :: integ -> integ -> integ
--- binary exclusive or, supposed to work like Java @^@ on all integral types
bxor :: integ -> integ -> integ
--- binary or, supposed to work like Java @|@ on all integral types
bor :: integ -> integ -> integ
--- binary left shift, supposed to work like Java @<<@ on all integral types
bshl :: integ -> Int -> integ
--- binary right shift, supposed to work like Java @>>@ on all integral types
bshr :: integ -> Int -> integ
--- unsigned right shift, supposed to work like Java @>>>@ on all integral types
ushr :: integ -> Int -> integ
--- one's complement, supposed to work like Java operator @~@
bcmpl :: integ -> integ
bcmpl x = x `bxor` fromInt (-1)
--- every integral number can be converted to a big 'Integer'
big :: integ -> Integer
-- -----------------------------------------------------
{--
'gcd' @x y@ is the non-negative factor of both @x@ and @y@ of which
every common factor of @x@ and @y@ is also a factor; for example
'gcd' @4 2 = 2@, @'gcd' (-4) 6 = 2@, @'gcd' 0 4@ = @4@. @'gcd' 0 0@ = @0@.
(That is, the common divisor that is \"greatest\" in the divisibility
preordering.)
Note: Since for signed fixed-width integer types, 'abs' 'minBound' < @0@,
the result may be negative if one of the arguments is 'minBound' (and
necessarily is if the other is @0@ or 'minBound') for such types.
-}
gcd :: integ -> integ -> integ
gcd x y = gcd' (abs x) (abs y)
where gcd' a b | b == zero = a
| otherwise = gcd' b (a `rem` b)
--- 'lcm' @x y@ is the smallest positive integer that both @x@ and @y@ divide.
lcm :: integ -> integ -> integ
lcm x y
| x == zero || y == zero = zero
| otherwise = abs ((x `quot` (gcd x y)) * y)
even, odd :: integ -> Bool
even n = n `band` one == zero
odd n = n `band` one != zero
--############ Int instances & functions ############################
instance Eq Int where
--- Uses the java @==@ operator for comparision of 'Int' values.
pure native == :: Int -> Int -> Bool
--- Uses the java @!=@ operator for comparision of 'Int' values.
pure native != :: Int -> Int -> Bool
instance Ord Int where
--- Uses the java @<=@ operator for comparision of 'Int' values.
pure native <= :: Int -> Int -> Bool
--- Uses the java @>=@ operator for comparision of 'Int' values.
pure native >= :: Int -> Int -> Bool
--- Uses the java @<@ operator for comparision of 'Int' values.
pure native < :: Int -> Int -> Bool
--- Uses the java @>@ operator for comparision of 'Int' values.
pure native > :: Int -> Int -> Bool
(<=>) :: Int -> Int -> Ordering
(a) <=> (b) = if a**b then Gt else Eq
instance Num Int where
--- Uses the java @+@ operator to add 2 'Int' values.
pure native + :: Int -> Int -> Int
--- Uses the java @\*@ operator to multiply 2 'Int' values.
pure native * :: Int -> Int -> Int
--- Uses the java @-@ operator to subtract one 'Int' value from another.
pure native - :: Int -> Int -> Int
--- the integer constant 0
zero = 0
--- the integer constant 1
one = 1
{-- Returns the negated argument if it is negative, otherwise the argument itself.
This does not work for 'Int.minBound' since there is no corresponding positive
value that can be represented as an 'Int'. Rather
> abs Int.minBound == Int.minBound
-}
abs i = if i < 0 then negate i else i
{-- @negate i@ computes @0-i@ using the java negation operator @-@.
This does not work for 'Int.minBound' since there is no corresponding positive
value that can be represented as an 'Int'. Rather
> negate Int.minBound == Int.minBound
-}
pure native negate "-" :: Int -> Int
--- For 'Int' values, this is the identity function.
fromInt i = i
instance Eq Long where
--- Uses the java @==@ operator for comparision of 'Long' values.
pure native == :: Long -> Long -> Bool
--- Uses the java @!=@ operator for comparision of 'Long' values.
pure native != :: Long -> Long -> Bool
instance Ord Long where
--- Uses the java @<=@ operator for comparision of 'Long' values.
pure native <= :: Long -> Long -> Bool
--- Uses the java @>=@ operator for comparision of 'Long' values.
pure native >= :: Long -> Long -> Bool
--- Uses the java @<@ operator for comparision of 'Long' values.
pure native < :: Long -> Long -> Bool
--- Uses the java @>@ operator for comparision of 'Long' values.
pure native > :: Long -> Long -> Bool
(<=>) :: Long -> Long -> Ordering
(a) <=> (b) = if a****b then Gt else Eq
instance Num Long where
--- Uses the java @+@ operator to add two 'Long' values.
pure native + :: Long -> Long -> Long
--- Uses the java @\*@ operator to multiply two 'Long' values.
pure native * :: Long -> Long -> Long
--- Uses the java @-@ operator to subtract a 'Long' value from another.
pure native - :: Long -> Long -> Long
--- The constant @0L@.
zero = 0L
--- The constant @1L@.
one = 1L
{-- Returns the negated argument if it is negative, otherwise the argument itself.
This does not work for 'Long.minBound' since there is no corresponding positive
value that can be represented as a 'Long'. Rather
> abs Long.minBound == Long.minBound
-}
abs i = if i < 0L then 0L-i else i
{-- @negate a@ computes @0L-a@ using the java negation operator @-@.
This does not work for 'Long.minBound' since there is no corresponding positive
value that can be represented as a 'Long'. Rather
> negate Long.minBound == Long.minBound
-}
pure native negate "-" :: Long -> Long
--- applys the widening primitive conversion (JLS §5.1.2) from @int@ to @long@
fromInt i = i.long
{--
* A class for data types that have a lower and an upper bound.
*
* Instances of 'Bounded' can be derived automatically for enumeration types.
-}
class Bounded b where
--- the lower bound
minBound :: b
--- the upper bound
maxBound :: b
instance Bounded Int where
--- the smallest 'Int' value -2147483648 (or -(2**31))
minBound = 0x80000000
--- the largest 'Int' value 2147483647 (or (2**31)-1)
maxBound = 0x7fffffff
instance Enum Int where
--- > ord i = i
ord (i::Int) = i
--- > from i = i
from (i::Int) = i
--- @pred i@ is the same as @i-1@ except for @pred Int.minBound@, which is 'undefined'
pred i
| i > Int.minBound = i-1
| otherwise = error "pred Int.minBound"
--- @succ i@ is the same as @i+1@ except for @succ Int.maxBound@, which is 'undefined'
succ i
| i < Int.maxBound = i+1
| otherwise = error "succ Int.maxBound"
instance Bounded Long where
--- the smallest 'Long' value -9223372036854775808 (or -(2**63))
minBound = 0x8000000000000000L
--- the largest 'Long' value 9223372036854775807 (or (2**63)-1)
maxBound = 0x7fffffffffffffffL
instance Enum Long where
--- @ord l@ is only valid if @Int.minBound.long <= l && l <= Int.maxBound@
ord (i::Long) = i.int;
--- @Long.from i@ returns a 'Long' with the same numeric value as @i@.
from (i::Int) = i.long;
--- @pred a@ is the same as @a-1L@ except for @pred Long.minBound@, which is 'undefined'
pred i
| i > Long.minBound = i-1L
| otherwise = error "pred Long.minBound"
--- @succ a@ is the same as @a+1L@ except for @succ Long.maxBound@, which is 'undefined'
succ i
| i < Long.maxBound = i+1L
| otherwise = error "succ Long.maxBound"
instance Integral Int where
pure native rem % :: Int -> Int -> Int
pure native quot / :: Int -> Int -> Int
pure native bshl "<<" :: Int -> Int -> Int
pure native bshr ">>" :: Int -> Int -> Int
--- unsigned right shift
pure native ushr ">>>" :: Int -> Int -> Int
pure native bcmpl "~" :: Int -> Int
big l = Integer.valueOf l.long
instance Integral Long where
pure native rem % :: Long -> Long -> Long
pure native quot / :: Long -> Long -> Long
pure native bshl "<<" :: Long -> Int -> Long
pure native bshr ">>" :: Long -> Int -> Long
pure native bcmpl "~" :: Long -> Long
big l = Integer.valueOf l
--- unsigned right shift
pure native ushr ">>>" :: Long -> Int -> Long
--############# Bool instances ########################################
instance Ord Bool where
false < true = true
_ < _ = false
true > false = true
_ > _ = false
false <= _ = true
true <= b = b
false >= b = !b
true >= _ = true
true <=> false = Gt
false <=> true = Lt
_ <=> _ = Eq
instance Bounded Bool where
minBound = false
maxBound = true
instance Enum Bool where
ord false = 0
ord true = 1
from 0 = false
from _ = true -- nonzero is true
pred true = false
pred _ = error "pred false"
succ false = true
succ true = error "succ true"
--############## String instances ###############
instance Eq String where
pure native == equals :: String -> String -> Bool
(!=) :: String -> String -> Bool
a != b = !(a==b)
instance Ord String where
(<=>) :: String -> String -> Ordering
(>) :: String -> String -> Bool
(<) :: String -> String -> Bool
(>=) :: String -> String -> Bool
(<=) :: String -> String -> Bool
a <=> b = (a.compareTo b).<=> 0
a > b = (a.compareTo b).> 0
a < b = (a.compareTo b).< 0
a >= b = (a.compareTo b).>= 0
a <= b = (a.compareTo b).<= 0
--################# Char instances #############
instance Eq Char where
pure native == :: Char -> Char -> Bool
pure native != :: Char -> Char -> Bool
instance Ord Char where
(<=>) :: Char -> Char -> Ordering
a <=> b = a.ord.<=> b.ord
pure native <= :: Char -> Char -> Bool
pure native >= :: Char -> Char -> Bool
pure native < :: Char -> Char -> Bool
pure native > :: Char -> Char -> Bool
instance Bounded Char where
pure native minBound java.lang.Character.MIN_VALUE :: Char
pure native maxBound java.lang.Character.MAX_VALUE :: Char
instance Enum Char where
pure native from "(char)" :: Int -> Char
pred c = Char.from (Char.ord c - 1)
succ c = Char.from (Char.ord c + 1)
chr i = Char.from i
pure native ctos java.lang.Character.toString :: Char -> String
--################# Float Instances #############
instance Eq Float where
pure native == :: Float -> Float -> Bool
pure native != :: Float -> Float -> Bool
instance Ord Float where
pure native <= :: Float -> Float -> Bool
pure native >= :: Float -> Float -> Bool
pure native < :: Float -> Float -> Bool
pure native > :: Float -> Float -> Bool
(<=>) :: Float -> Float -> Ordering
a <=> b = if a****b then Gt else Eq
instance Real Float where
pure native + :: Float -> Float -> Float
pure native - :: Float -> Float -> Float
pure native * :: Float -> Float -> Float
pure native / :: Float -> Float -> Float
zero = 0.0f
one = 1.0f
pure native negate "-" :: Float -> Float
fromInt i = i.float
pure native isInfinite java.lang.Float.isInfinite :: Float -> Bool
pure native isNaN java.lang.Float.isNaN :: Float -> Bool
-- ################# Double Instances #############
instance Eq Double where
pure native == :: Double -> Double -> Bool
pure native != :: Double -> Double -> Bool
instance Ord Double where
pure native <= :: Double -> Double -> Bool
pure native >= :: Double -> Double -> Bool
pure native < :: Double -> Double -> Bool
pure native > :: Double -> Double -> Bool
(<=>) :: Double -> Double -> Ordering
a <=> b = if a****b then Gt else Eq
instance Real Double where
pure native + :: Double -> Double -> Double
pure native - :: Double -> Double -> Double
pure native * :: Double -> Double -> Double
pure native / :: Double -> Double -> Double
zero = 0.0
one = 1.0
pure native negate "-" :: Double -> Double
fromInt i = i.double
pure native isInfinite java.lang.Double.isInfinite :: Double -> Bool
pure native isNaN java.lang.Double.isNaN :: Double -> Bool
-- ################# Misc. types and derivations #############
-- derive Show ()
-- derive Show Ordering
instance Eq Eq a => [a] where
--- two lists are equal if their heads and tails are equal or if the lists are empty
(a:as) == (b:bs) | a == b = as == bs
| otherwise = false
[] == [] = true
_ == _ = false
hashCode [] = 31
hashCode as = loop as 32
where
loop (a:as) !acc = loop as (acc*31 + hashCode a)
loop [] acc = acc
-- derive Ord Ord a => [a]
data Maybe a = Nothing | Just a
{--
The 'maybe' function takes a default value, a function, and a 'Maybe' value.
If the 'Maybe' value is 'Nothing', the function returns the default value.
Otherwise, it applies the function to the value inside the 'Just' and returns the result.
-}
maybe d f (Just x) = f x
maybe d f Nothing = d
data Either a b = Left a | Right b
-- derive Eq Either a b
-- derive Ord Either a b
-- derive Show Either a b
either left right (Left x) = left x
either left right (Right x) = right x
{--
* > string =~ regex
* tries to match _string_ against _regex_ and returns
* @Just matcher@ if it succeeds, @Nothing@ otherwise.
-}
(s) =~ (p::Regex) = (p.matcher s).find
{--
* >string ~ regex
* @true@ if _string_ matches _regex_, @false@ otherwise
-}
(s) ~ (p::Regex) = case (p.matcher s).find of
Just _ -> true
Nothing -> false
{--
* > s !~ p == !(s ~ p)
-}
(s) !~ (p) = !(s ~ p)
{--
* > ("string" ~~ #r??#) == Just "rin"
* Tries a match and returns @Just x@ where
* _x_ is the matched substring or @Nothing@ if there was no match.
*
-}
s ~~ r =
case s =~ r of
Just m -> m.group 0
Nothing -> Nothing
{--
* > string ~~~ regex
* Matches _string_ with _regex_ and returns a function
* that can be used to extract the matched part of the string and the
* captured substrings.
* > let f = "frege" ~~~ #(..).(..)#
* > in [ f i | i <- 0..3 ]
* yields
* >[Just "frege", Just "fr", Just "ge", Nothing]
-}
s ~~~ r =
case s =~ r of
Just m -> m.group
Nothing -> const Nothing
{--
* @m ?~ p@ binds pattern _p_ to the matcher _m_
* and tries a match. There must have been a successful
* match on _m_ before.
* Returns 'Nothing' if match fails, else ('Just' @m@).
* This function is most usefull in conjunction with patterns that
* use the G-anchor when one wants to extract
* multiple differnt adjacent items from a string.
-}
(m::Matcher) ?~ (p) = m.usePatternAndFind p
{--
* > m /~ p
* is like
* > m ?~ p
* but instead of the
* matcher it returns the matched string, if any.
-}
(m) /~ (p) = case m ?~ p of
Just m -> Matcher.group m 0
Nothing -> Nothing
--- return the first element of a 2-tuple
fst (a, _) = a
--- return the second element of a 2-tuple
snd (_, a) = a
-- derive Eq (a,b)
-- derive Ord (a,b)
-- derive Show (a,b)
-- derive Eq (a,b,c)
-- derive Ord (a,b,c)
-- derive Show (a,b,c)
{- more tuple stuff in Tuples.fr -}
-- function stuff
{--
Function composition.
@(f <~ g)@ is a function whose argument is
passed to /g/, and the result to /f/, yielding the overall result.
One can imagine that the data flow from right to left through a function pipe.
> (a) <~ (b) = \x -> a (b x)
-}
(a) <~ (b) = \x -> a (b x)
{--
Function composition.
@(f ~> g)@ is a function whose argument is first
passed to /f/, and the result to /g/, yielding the overall result.
One can imagine that the data flows from left to right through a function pipe.
> (a) ~> (b) = \x -> b (a x)
-}
(a) ~> (b) = \x -> b (a x)
{--
@a $ b@ is the same as @a b@, but because of '$''s low precedence
one can write @f $ x+y@ instead of @f (x+y)@. Also, becuase '$' is right
associative, @f $ g $ h y@ is @f (g (h y))@
-}
(a) $ (b) = a b
--- Same as `$` but argument is strict
a $! !b = a b
--- The identity function
id x = x
--- @const a@ is a function that returns _a_ regardless of its argument.
const a _ = a
--- @asTypeOf a b@ is _a_ with the type of _b_.
--- This is a type restricted version of 'const'.
asTypeOf :: a -> a -> a
asTypeOf a _ = a
--- Exchange first and second argument of a function, i.e.
--- > flip f a b = f b a
flip f a b = f b a
--- Passes the elements of a 2-tuple as arguments to a function.
uncurry f (a,b) = f a b
--- @curry f@ passes the next two arguments as 2-tuple to _f_
curry f a b = f (a,b)
--- Another operator for function composition, which is identical to '<~'
--- > (f • g) a = f (g a)
(•) = \f\g\a -> f (g a)
--- In patterns, the \@-operator is used to bind a name to a complex pattern
--- > f (x@a:as) = e
--- is the same as
--- > f arg = case arg of { x -> case x of { a:as -> e }}
(@) = (•)
{--
* @using f@ applies a projection function _f_ on both sides of '=='.
* The example for 'uniqBy' could be written easier
* > uniqBy (using fst) [(1, 1), (2, 2), (2, 3), (3,4), (2,5)]
-}
using f a b = f a == f b
{--
* @comparing f@ applies a proejction function on both sides of '<=>'.
* Example usage:
* > sortBy (comparing snd) [(1, "z"), (2, "b")] == [(2, "b"), (1, "z")]
-}
comparing f a b = f a <=> f b
--- this is just an alias for 'comparing'
ascending = comparing
{--
* @descending f@ applies a projection function on both sides of '<=>', but flips arguments.
* Example usage:
* > sortBy (descending fst) [(1, "z"), (2, "b")] == [(2, "b"), (1, "z")]
-}
descending f a b = f b <=> f a
-- ####################################################################
-- ###################### monad stuff #################################
-- ####################################################################
{--
* @(ST s a)@ is an abstract data type and is
* a computation that encapsulates side effects in state thread @s@
* and returns a value of type @a@.
* The type @s@ can be understood as a compiler generated unique index for state threads.
* Every state thread is independend of each other and keeps track of mutable variables
* created in it. For detailed information, read the paper _Lazy Functional State Threads_.
* Every mutable native data type will have a phantom type paramter @s@
* that tells to what state thread the value belongs. For example, the @new@ method of
* the java class @java.util.Date@ could be accessed like this:
> data Date s = native java.util.Date where
> native new :: () -> ST s (Date s)
* Inside ST actions, Date values can be created and manipulated with
* impure native methods at will. However, such a value can never escape
* its ST thread.
* Because @ST s@ is an instance of 'Monad', ST actions can be combined, which
* ensures sequenced execution. For example, we could add another method
* to the Date type that converts the date to a string:
* > native toString :: Date s -> ST s String
* and a computation which yields the current time in string form:
* > now = do
* > date <- Date.new ()
* > return date.toString
* This looks almost like java already! @now@ has type @ST s String@ and we can run
* the computation with @now.run@ (see 'ST.run' below), which gives us a nice, pure, immutable,
* functional correct 'String' value.
* The 'IO' type is just an alias for 'ST' 'RealWorld', and can be thought of as
* indexing a unique global state thread.
* Values of type 'IO' @a@ are also called _IO actions_.
* Any ST value can also be used in the IO thread.
* This guarantees that
* - any computation with side effect is sequenced through the ST-Monad
* - any function whose return type is not @IO something@ does not have side effects,
* as long as no impure native function or value is deliberately declared to be pure.
-}
abstract data ST s a = ST (s -> a) where
private app :: ST s a -> s -> a
private app (ST x) b = x b
{--
Run a stateful action with type @ST r a@ and return a result of type _a_.
The overall computation @ST.run st@ is pure, though inside the 'ST' action
local mutable state can be employed.
This is possible only if the result type @a@ of the state action does *not* mention
@r@ and if @r@ is a type variable. Hence, it is not possible to 'run' an 'IO' action.
-}
public run :: forall a . (forall ß. ST ß a) -> a
public run stx = (stx.app "stateful")
public performUnsafe (ST x) = (x RealWorld.RealWorld)
-- The function that does the real work for 'ST.>>='
-- It is defined public in order to make inlining possible
-- public bind :: (x -> y) -> (y -> ST x z) -> x -> z
-- public bind a k u = case a u of
-- !v -> case k v of ST.ST b -> b u
public return a = ST (const a)
public (ST !a) >>= k = ST (\u -> case a u of
!v -> case k v of ST.ST b -> b u
)
{--
* This abstract data type identifies the global state (disk, network, you name it).
* Values of type 'ST' 'RealWorld' @a@ are likely to perform input/output, manipulate
* global data and so on.
-}
abstract data RealWorld = RealWorld
{--
* Some native values can be detached from the stateful realm so as to make it possible
* to apply them to pure (native) functions, see 'Freezable'.
*
* Such values will have 'Immutable' as last type argument.
-}
abstract data Immutable = Immutable
--- @IO a@ is an abbrevation for 'ST' 'RealWorld' @a@
type IO = ST RealWorld
--- @Mutable MyType s@ is an abbrevation for 'ST' @s (MyType s)@
type Mutable n s = ST s (n s)
--- @Frozen MyType@ is an abbrevation for @MyType Immutable@
type Frozen n = n Immutable
-- --- @IOJ T@ is an abbreviation for 'IO' (T 'RealWorld')
-- --- @STJ s T@ is an abbreviation for 'ST' s (T s)
-- type IOJ j = STJ RealWorld j
-- type STJ s j = ST s (j s)
-- ########## Variables ###########################
data STRef a s = native frege.rt.Ref where
native new :: a -> Mutable (STRef a) s
native get :: STRef a s -> ST s a
native put :: STRef a s -> a -> ST s ()
type IORef a = STRef a RealWorld
{--
* @State s a@ is an abstrac data type that resembles a stateful computation
* with state _s_ and result _a_,
* i.e. functions of type @s -> (a, s)@
* where the state is immutable.
-}
abstract data State s a = State (s -> (a, s)) where
--- run a stateful computation
public run (State x) s = x s
--- get the current 'State'
public get = State (\state -> (state; state))
--- update the 'State'
public put x = State (const ((); x))
--- change the 'State'
public change f = State (\state -> ((); f state))
--- lift a value to the 'State' monad
public return a = State (strictTuple2 a)
--- monadic bind for the 'State' monad
public State !a >>= k = State (\s -> case a s of
(v, !s') -> case k v of
State.State b -> b s'
)
public a >> b = State.>>= a (const b)
--- print a 'string' to the standard error stream
native traceStr java.lang.System.err.print :: String -> IO ()
--- print a 'string' to the standard error stream and append a new line.
native traceStrLn java.lang.System.err.println :: String -> IO ()
--- print a 'string' to the standard output stream
native printStr java.lang.System.out.print :: String -> IO ()
--- print a 'string' to the standard output stream and append a new line.
native printStrLn java.lang.System.out.println :: String -> IO ()
**