Skip to content

A pure functional, statically typed, non-strictly evaluated golfing language.

License

Notifications You must be signed in to change notification settings

AugmentedFifth/schonfinkel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Schönfinkel

Schönfinkel is a pure functional, statically typed (with full type inference), non-strictly evaluated golfing language.

Schönfinkel acts as a golfed "bridge" to the Haskell language.

!!!info!!! Schönfinkel is under active development and is by no means a finished product; as such, expect features to appear and disappear or even full changes in semantics to occur without prior notice. !!!/info!!!

Essentially all Schönfinkel code constructs map directly to Haskell counterparts. Schönfinkel does, however, define alternate syntax for many constructs as well as several builtins. To do this, Schönfinkel defines a custom code page that covers the same range as ASCII (1 byte per character), but with non-printable ASCII characters (including TAB) replaced with custom symbols. See here for the full codepage listed in an easy-to-read format.

Getting started; implementation

Since the Schonfinkel compiler is written in JavaScript, the easiest way to get started is to just hit up the "Try now" here, online. It offers a text editor with buttons for inserting non-ASCII characters, a syntax-highlighted preview, and instant compilation into Haskell.

The Schönfinkel compiler can also be used as a command-line tool, provided that the user has node installed.

!!!button!!! The node version of the compiler can be downloaded here. !!!/button!!!

!!!info!!! Make sure to set the executable bit on the sch file, that way

$ ./sch

can be directly run from the command line. (The above assumes that the user is in the same directory as the file.) !!!/info!!!

The CLI version of the Schönfinkel compiler offers two methods of decoding the specified file.

$ ./sch -c <inputFile> [outputFile]

Will read in <inputFile> and interpret it using the custom codepage. This generally isn't useful, but is the official method insofar as it's the only way for each character in the language to constitute exactly one byte. Once the compilation is done, it will be output either to [outputFile], or, if that's not specified, a variation of the input file's name (with a .hs extension) will be used instead.

$ ./sch -u <inputFile> [outputFile]

...is the more usual use case. The -u flag stands for Unicode, and reads in the file assuming UTF-8 encoding. Otherwise this is the same.

Haskell, you say?

The compiler just emits Haskell, so there's more steps to be taken after the transpilation. Many will already have access to a Haskell compiler with which to compile the resulting .hs file for execution (or, which also works, an interpreter). For those who don't, I recommend the use of Stack, or just any plain old installation of the GHC. Some online REPLs exist that could maybe work, like TryHaskell.

The Schonfinkel compiler really only acts as a syntax-level transpiler to Haskell, so you can expect blatant type errors and other errors like referencing non-existent variables to "compile" to Haskell just fine, only to fail miserably upon hiting the GHC (or Hugs or whatever). Thus:

!!!info!!! Compiling the emitted Haskell code is the real test of program validity! !!!/info!!!

Identifiers

One quirk of Schönfinkel is that all identifiers used by the programmer (i.e., that are not pre-defined) must consist solely of lowercase letters (i.e., must match the regex [a-z]+). The only exception to this rule is programmer-defined infix functions. Characters in the range [A-Z] are reserved for builtins. Underscores (_) have only one meaning in Schönfinkel, namely, empty patterns/throwaway variables. Characters in the range [0-9] are reserved for numeric literals exclusively.

Additionally, the first 5 lowercase letters as a single identifier (a, b, c, d, e) are identifiers reserved for implicit input/command-line arguments. b, c, d, and e are the 1st, 2nd, 3rd, and 4th inputs to the program, in order, as Strings.

!!!info!!! NOTE: These bindings are only visible inside of "naked" top-level expressions (see the "Whole-program semantics" section), so everywhere else, these identifiers are not reserved. !!!/info!!!

If less than 4 arguments are supplied, the remaining variables are just the empty string (""). If more than 4 arguments are supplied, b, c, d, and e are assigned normally, and a is always a list of all arguments supplied (of type [String]), so all arguments are always accessible.

Infix functions: The exception to the rule

Infix functions can still be defined normally like in Haskell. The characters available to be used are slightly different: for one-character infix functions defined by the programmer, the options are !, ?, #, &, and ~. Infix functions with more characters (generally 2 at most) can combine those characters as well as the following other characters: $, <, >, ^, : (so long as it doesn't start with :), +, -, @, %, ., \, =, and *.

Advantages to simple and restricted syntax

Because of the restrictions on identifier names and their semantics, Schönfinkel allows omitting whitespace more often than in Haskell:

a=[1..9]
La -- yields `9`

L is a pre-defined function (equivalent to Haskell's genericLength), so it consists only of uppercase letters. This allows it to be differentiated from a, which is another distinct token. In Haskell this would have to be L a (note the space in between). Just like in Haskell, function invocations can be made in infix form even for alphabetically-named functions. In Haskell, this is achieved by simply surrounding the function identifier with backticks (`). However, in Schönfinkel there is no backtick on the right side of the identifier. Instead, the "missing" backtick is "automatically inserted" just before the next character that either

  • isn't alphabetic, or
  • is of a different case (lower → upper or vice versa).

For example:

", "`U["one","two","three","four"]

U is essentially Haskell's intercalate. Here, it is used as an infix function where the initial backtick captures the U and then continues on until it finds a non-alphabetic character or a letter that is of a different case (lowercase). It immediately runs into the [ character, so the backtick is inserted just before that, yielding an interpretation of

", "`U`["one","two","three","four"]

!!!warn!!! N.B.: The above snippet isn't actually valid Schönfinkel since it would be trying to make the list literal into an infix function. !!!/warn!!!

This is the same thing:

y=["one","two","three","four"]
", "`Uy

An even funkier way to use backticks

Backticks can also be used on functions that are infix to begin with (i.e. they take in exactly two arguments and don't have any letters in the name). This has essentially the same syntax rules as above, but instead of turning into an infix function, it makes the function behave as if the Haskell function flip were applied to it. That is, the order of its arguments are reversed:

(+1)[1..5]  -- [2, 3, 4, 5, 6]

[1..5]\`(+1) -- [2, 3, 4, 5, 6]

Bindings

let/where bindings work similarly to Haskell, but have more concise syntax. Variables are still bound using =, but instead of let ... in ... or ... where ..., Schönfinkel uses curly brackets ({}) and separates bindings using commas (,). As an example, the following Schönfinkel code:

{x=3,y=1.5}x/y

...is identical to the following Haskell code:

let x = 3
    y = 1.5
in  x / y

Leftward-facing bindings (<-) in do blocks, guards, and list comprehensions work identically as in Haskell, but use a single character () instead.

Conditionals

Schönfinkel uses shortened conditional notation for if/else if/else constructs similar to the GHC extension "MultiWayIf", but without the if. To avoid ambiguity, Schönfinkel uses a special character (¦) for the vertical pipe character found in all list comprehensions (and additionally in case expressions, as will be seen later). For example,

v=[(-1, 8), (-1, 3), (23, 1), (1, 1)]

[|i>j→-2|i<j1|→0¦(i,j)v]

yields the list [1, 1, -2, 0]. The equivalent Haskell is:

v=[(-1, 8), (-1, 3), (23, 1), (1, 1)]

[if i > j then -2 else if i < j then 1 else 0 | (i, j) <- v]

As you can see, omitting the condition (|→) always matches; it's the same as matching on True in Haskell (|True->), or just the else keyword.

It's common to get away with not using the && function when logical AND is needed. Instead, guards and multi-way "if"s like the one above can have multiple conditions chained together using commas (,). For example, |i>j,i>0→ is the same as |i>j&&i>0→.

Ranges

Ranges work essentially the same as in Haskell, with one small change. Descending ranges that don't use comma(s) work as expected in Schönfinkel. That is,

[9..1]

is the same as the following Haskell:

[9,8..1]

Case expressions

Schönfinkel uses a shortened form of case expressions that otherwise work the same way as their Haskell counterparts. The following Haskell:

f x =
    case x of
        0 -> 18
        1 -> 15
        2 -> 12
        _ -> 12 + x

can be translated directly into Schönfinkel as (note the angle brackets, ⟨ ⟩, distinct from less than/greater-than symbols, < >):

f x=⟨x¦018¦115¦212¦→12+x

Creative use of commas for cases

Additionally, multiple possible matches can map to the same expression easily and without redundancy using commas (,). The following Haskell:

f x =
    case x of
        0 -> 18
        1 -> 16
        2 -> 16
        _ -> 12 + x

can be translated directly into Schönfinkel as:

f x=⟨x¦018¦1,216¦→12+x

do notation

do notation works in Schönfinkel much the same way as in Haskell, but instead of the word do, the character is used instead. This saves the programmer from having to write the o and the whitespace(s) after it. Additionally, as mentioned before, monadic bindings use instead of <-.

Semicolons (;) are used to separate statements within a do block just like in Haskell, except that Schönfinkel offers no "sections," i.e. using linefeeds and indentation to provide separate statements. So you're stuck with semicolons.

Whitespace

The only whitespace that is really significant in Schönfinkel is line feeds ('\n'; LF; codepoint 0x0A). Spaces (' '; codepoint 0x20), the only other kind of whitespace, are only significant when they are needed to distinguish one token from another, e.g.

Lab

Applies the L function to ab, whereas

La b

applies the L function to a and is then followed by b. And of course, spaces are significant inside of character and string literals.

Line feeds, on the other hand, separate semantic contexts. Once a line feed is inserted, any context (like bindings and their values) is no longer visible except for so-called "top-level bindings", which are bindings made flush to the left (i.e. at the very beginning of a line). Just like in Haskell, this is the only way to define a function visible "globally":

f={i=1}(Δi).L
g=f[0..7]

f is visible within the semantic context of g because f is defined as a top-level binding, but i is not visible; it was bound inside of f's context.

Of course, we might want to have nested contexts. For this, parentheses (( )) can be used. Bindings made within a pair of parentheses are not visible anywhere outside of them:

f x=({l=W(<3)x}l)l  -- Very bad!

The above won't work, because the second time that l is mentioned is outside of the parentheses that it was bound in. Since the parentheses are dictating the semantic context in this case, there's no such thing as l outside of them.

Automatic bracket insertion

Similar to many calculators, Schönfinkel will happily assume that you meant to add any of the following closing brackets:

  • )
  • ]

at the end of a line (i.e. just before a linefeed \n), provided that they are "expected" (i.e. their left-hand counterparts are still on the stack). As a very simple example, the following works just fine to define a function that doubles its argument:

f=(*2

It still works even when there's nesting, too. Just treat it like a stack:

f x=⟨x¦0(+)¦→(*

...is the same as:

f x=⟨x¦0(+)¦→(*)

Comments

Comments are the same style as Haskell; more precisely, a block comment matches:

/{-[\s\S]*-}/

A line comment, then, matches:

/--[^\n]*/

Tuples

Tuple syntax is almost entirely the same as in Haskell, with a small exception. Schönfinkel uses Haskell's "TupleSections" language mode by default. In Haskell:

{-# LANGUAGE TupleSections #-}

t = ("!-", , "-!") <$> [0..2]

Here, t is [("!-", 0, "-!"), ("!-", 1, "-!"), ("!-", 2, "-!")]. As you can see, this essentially means that tuple constructors (normally like (,) or (,,)) can be partially applied. And, notably, the partial application can occur anywhere in any n-tuple constructor.

Whole-program semantics

Unlike Haskell, Schönfinkel can have "naked" expressions at top-level. "Naked" here refers to expressions that aren't bound to anything. In Haskell this makes no sense, since the expression is then unusable/useless. In Schönfinkel, however, any top-level naked expressions that are encountered in the source code (reading from top to bottom) are considered the program's main body. If there are multiple such naked expressions (i.e. separated by line feeds), then the expressions are considered in order of occurence.

Naked expressions that don't already have a type of IO a are automatically wrapped up into expressions of type IO (), by simply printing their values to stdout, after being shown and having a line feed appended to the resulting String. Now that all naked expressions have a type of IO a, they are called as if from the main function, in order of occurence, chained using the >> function (i.e. any "return values", trivial or nontrivial, are discarded).

Codepage

!!!codepage!!!

1-byte built-in functions

Equivalent of Control.Applicative.<*> in Haskell.

Infix?: yes

Equivalent of Data.Eq.== in Haskell.

Infix?: yes

Equivalent of Data.Eq./= in Haskell.

Infix?: yes

¬

Equivalent of Data.Bool.not in Haskell.

Infix?: no

Equivalent of Data.List.findIndices in Haskell.

Infix?: yes; infixl 8

Splits a list at every occurence of another given list of the same type.

Infix?: yes; infixl 5

Haskell implementation of this function:

import Data.List

infixl 5 ⩖
(⩖) :: Eq a => [a] -> [a] -> [[a]\]
(⩖) l n =
    fst $ until (\(_, ll) -> null ll) (\(accu, rest) ->
        if genericTake needleLen rest == n then
            (accu ++ [[]], genericDrop needleLen rest)
        else
            (init accu ++ [last accu ++ [head rest]], tail rest)) ([[]], l)
    where needleLen = genericLength n

Equivalent of Control.Monad.mapM in Haskell.

Infix?: yes; infixl 5

Equivalent of Data.Foldable.elem in Haskell.

Infix?: yes

Equivalent of Control.Arrow.*** in Haskell.

Infix?: yes

Equivalent of Control.Arrow.&&& in Haskell.

Infix?: yes

Equivalent of Control.Monad.>> in Haskell.

Infix?: yes

Equivalent of Data.List.intersect in Haskell.

Infix?: yes; infixl 5

Equivalent of Data.List.union in Haskell.

Infix?: yes; infixl 5

Σ

Equivalent of Data.Foldable.sum in Haskell.

Infix?: no

Equivalent of Control.Applicative.<$> in Haskell.

Infix?: yes

Equivalent of Data.List.partition in Haskell.

Infix?: yes; infixl 5

Equivalent of Data.Foldable.all in Haskell.

Infix?: yes; infixl 5

Equivalent of Data.Foldable.any in Haskell.

Infix?: yes; infixl 5

¡

Equivalent of Data.List.genericIndex in Haskell.

Infix?: yes; infixl 8

Δ

Equivalent of Prelude.subtract in Haskell.

Infix?: yes; infixl 6

N.B.: The ASCII hyphen/minus sign (-) cannot be used for subtraction, since it only serves to negate numbers (e.g. -2.5). Instead, this function should be used.

Equivalent of Prelude.floor in Haskell.

Infix?: no

×

Takes the cartesian product of two lists.

Infix?: yes; infixl 5

Haskell implementation of this function:

infixl 5 ×
(×) :: [a] -> [b] -> [(a, b)]
(×) xs ys = [(x, y) | x <- xs, y <- ys]

Equivalent of Data.List.zip in Haskell.

Infix?: yes; infixl 5

÷

Equivalent of Prelude.div in Haskell.

Infix?: yes

$

Unchanged from Haskell.

%

Equivalent of Prelude.mod in Haskell.

Infix?: yes

*

Unchanged from Haskell.

+

Unchanged from Haskell.

-

Equivalent of Prelude.negate in Haskell.

Infix?: no

N.B.: The ASCII hyphen/minus sign (-) cannot be used for subtraction, since it only serves to negate numbers (e.g. -2.5). Instead, the Δ function should be used.

.

Unchanged from Haskell.

/

Unchanged from Haskell.

:

Unchanged from Haskell.

<

Unchanged from Haskell.

>

Unchanged from Haskell.

^

Unchanged from Haskell.

Appends the right argument to the end of the left argument.

Infix?: yes; infixr 5

Haskell implementation of this function:

infixr 5 
(⋄) :: [a] -> a -> [a]
(⋄) l a = l ++ [a]

A

Equivalent of Data.List.filter in Haskell.

B

Equivalent of Data.List.sortBy in Haskell.

Mnemonic: sortBy

C

Equivalent of Data.Foldable.concat in Haskell.

Mnemonic: Concat

D

Equivalent of Data.List.nub in Haskell.

Mnemonic: Distinct

E

Equivalent of Data.Foldable.maximum in Haskell.

Mnemonic: Extremum

F

Equivalent of Data.List.zipWith in Haskell.

G

Equivalent of Data.Foldable.minimum in Haskell.

H

Equivalent of Prelude.toEnum in Haskell.

I

Equivalent of Data.Foldable.null in Haskell.

Mnemonic: unInhabited

J

Equivalent of Data.List.tail in Haskell.

K

Equivalent of Data.List.genericTake in Haskell.

Mnemonic: taKe

L

Equivalent of Data.List.genericLength in Haskell.

Mnemonic: Length

M

Equivalent of Prelude.show in Haskell.

N

Equivalent of Prelude.read in Haskell.

O

Equivalent of Prelude.fromEnum in Haskell.

Mnemonic: Ordinal

P

Equivalent of System.IO.print in Haskell.

Mnemonic: Print

Q

Replaces the given index of a list with a certain value. Does not change the length of the list. Accepts negative indices, viz. an index of -1 signifies the last index of the list, -2 signifies the second-to-last index, etc.

Haskell implementation of this function:

import Data.List

Q :: Integral i => i -> a -> [a] -> [a]
Q i a (b:bs)
    | i < 0     = Q (genericLength bs + i + 1) a (b:bs)
    | i == 0    = a:bs
    | otherwise = b : Q (i - 1) a bs

R

Equivalent of Data.List.reverse in Haskell.

Mnemonic: Reverse

S

Equivalent of Data.List.sort in Haskell.

Mnemonic: Sort

T

Equivalent of Data.List.transpose in Haskell.

Mnemonic: Transpose

U

Equivalent of Data.List.intercalate in Haskell.

Mnemonic: Unwords/Unlines

V

Equivalent of Data.List.scanl in Haskell.

W

Equivalent of Data.List.takeWhile in Haskell.

Mnemonic: take While

X

Equivalent of Data.Foldable.foldl' in Haskell.

Y

Equivalent of Data.Foldable.foldr in Haskell.

Z

Equivalent of Data.List.permutations in Haskell.

2-byte built-in functions

≫=

Equivalent of Control.Monad.>>= in Haskell.

Infix?: yes

≫>

Equivalent of Control.Arrow.>>> in Haskell.

Infix?: yes

≫^

Equivalent of Control.Arrow.>>^ in Haskell.

Infix?: yes

≪<

Equivalent of Control.Arrow.<<< in Haskell.

Infix?: yes

≪^

Equivalent of Control.Arrow.<<^ in Haskell.

Infix?: yes

⌊^

Equivalent of Prelude.ceiling in Haskell.

Infix?: no

⌊#

Equivalent of Prelude.round in Haskell.

Infix?: no

⌊!

Equivalent of Prelude.truncate in Haskell.

Infix?: no

&&

Unchanged from Haskell.

$>

Equivalent of Data.Functor.$> in Haskell.

*>

Equivalent of Control.Applicative.*> in Haskell.

Infix?: yes

**

Unchanged from Haskell.

++

Unchanged from Haskell.

<=

Unchanged from Haskell.

<$

Equivalent of Control.Applicative.<$ in Haskell.

Infix?: yes

<*

Equivalent of Control.Applicative.<* in Haskell.

Infix?: yes

=≪

Equivalent of Control.Monad.=<< in Haskell.

Infix?: yes

=<

Equivalent of Control.Monad.<=< in Haskell.

Infix?: yes

=>

Equivalent of Control.Monad.>=> in Haskell.

Infix?: yes

>=

Unchanged from Haskell.

^^

Unchanged from Haskell.

^≫

Equivalent of Control.Arrow.^>> in Haskell.

Infix?: yes

^≪

Equivalent of Control.Arrow.^<< in Haskell.

Infix?: yes

||

Unchanged from Haskell.

AB

Equivalent of Prelude.abs in Haskell.

Mnemonic: ABsolute value

AR

Equivalent of Control.Arrow.arr in Haskell.

Mnemonic: ARrow

BR

Equivalent of Data.List.break in Haskell.

Mnemonic: BReak

CA

Takes in a list and returns the Cartesian product of that list with itself. Note that unlike the × function, this function returns the ordered pairs as lists of length 2, not 2-tuples, since the types of both sides of the pair are guaranteed to be the same.

Mnemonic: reflexive CArtesian product

Implementation in Haskell:

CA :: [a] -> [[a]]
CA l = [[x, y] | x <- l, y <- l]

CG

Equivalent of Data.Ord.comparing in Haskell.

Mnemonic: ComparinG

CM

Equivalent of Data.Ord.compare in Haskell.

Mnemonic: CoMpare

CO

Equivalent of Prelude.cos in Haskell.

Mnemonic: COsine

CR

Equivalent of Data.Tuple.curry in Haskell.

Mnemonic: CuRry

CT

Equivalent of Prelude.const in Haskell.

Mnemonic: ConsTant

CU

Takes in an integer and returns a list of the integers from 0 to that integer, both inclusive. Works for both positive and negative integers.

Mnemonic: CoUnt

Implementation in Haskell:

CU :: Integral i => i -> [i]
CU n | n >= 0    = [0..n]
     | otherwise = [0,-1..n]

CV

Takes in an integer and returns a list of the integers from 1 to that integer if the integer is positive, and a list of the integers from -1 to that integer if it's negative. Both bounds are inclusive. Returns the empty list when the input is 0.

Mnemonic: CoU+1=Vnt

Implementation in Haskell:

CV :: Integral i => i -> [i]
CV n | n >= 1    = [1..n]
     | otherwise = [-1,-2..n]

CY

Equivalent of Data.List.cycle in Haskell.

Mnemonic: CYcle

DI

Equivalent of Data.Char.digitToInt in Haskell.

Mnemonic: Digit to Integer

DR

Equivalent of Data.List.genericDrop in Haskell.

Mnemonic: generic DRop

DW

Equivalent of Data.List.dropWhile in Haskell.

Mnemonic: Drop While

EI

Equivalent of Data.List.elemIndex in Haskell.

Mnemonic: Elem Index

EJ

Equivalent of Data.List.elemIndices in Haskell.

Mnemonic: Elem I+1=Jndices

EO

Counts occurrences of the first argument in the second argument. Second argument must be Foldable.

Mnemonic: Enumerate Occurrences

Implementation in Haskell:

import Data.Foldable

EO :: (Eq a, Foldable f, Integral i) => a -> f a -> i
EO needle haystack =
    foldl' (\count elem ->
        count + if elem == needle then 1 else 0) 0 haystack

ER

Equivalent of Prelude.error in Haskell.

Mnemonic: ERror

EV

Equivalent of Prelude.even in Haskell.

Mnemonic: EVen

EX

Equivalent of Prelude.exp in Haskell.

Mnemonic: EXponential

FA

Equivalent of Prelude.False in Haskell.

Mnemonic: FAlse

FC

Similar to Data.Foldable.find in Haskell, but returns undefined on failure (very dangerous!) instead of using Maybe to represent success/failure.

Mnemonic: FinD-1=C

Haskell implementation of this function:

import Data.List

FC :: (a -> Bool) -> [a] -> a
FC p l =
    case find p l of
        Just a -> a
        _      -> undefined

FD

Equivalent of Data.Foldable.find in Haskell.

Mnemonic: FinD

FH

Similar to Data.List.findIndex in Haskell, but returns -1 on failure instead of using Maybe to represent success/failure.

Mnemonic: Find I-1=Hndex

Haskell implementation of this function:

import Data.List

FH :: (a -> Bool) -> [a] -> Int
FH p l =
    case findIndex p l of
        Just i -> i
        _      -> -1

FI

Equivalent of Data.List.findIndex in Haskell.

Mnemonic: Find Index

FJ

Equivalent of Data.Maybe.fromJust in Haskell.

Mnemonic: From Just

FL

Equivalent of Data.List.foldl1' in Haskell.

Mnemonic: Fold Left 1'

FM

Equivalent of Data.Maybe.fromMaybe in Haskell.

Mnemonic: From Maybe

FP

Equivalent of Prelude.flip in Haskell.

Mnemonic: FliP

FR

Equivalent of Data.Foldable.foldr1 in Haskell.

Mnemonic: Fold Right 1

FS

Equivalent of Control.Arrow.first in Haskell.

Mnemonic: FirSt

FT

Equivalent of Data.Tuple.fst in Haskell.

Mnemonic: FirsT

GC

Equivalent of System.IO.getChar in Haskell.

Mnemonic: Get Character

GD

Equivalent of Prelude.gcd in Haskell.

Mnemonic: Greatest common Divisor

GL

Equivalent of System.IO.getLine in Haskell.

Mnemonic: Get Line

IA

Equivalent of Data.Char.isAlpha in Haskell.

Mnemonic: Is Alphabetical

IC

Equivalent of Data.Char.intToDigit in Haskell.

Mnemonic: Integer to D-1=Cigit

ID

Equivalent of Prelude.id in Haskell.

Mnemonic: IDentity

IE

Equivalent of Data.List.iterate in Haskell.

Mnemonic: ItErate

IJ

Equivalent of Data.Maybe.isJust in Haskell.

Mnemonic: Is Just

IL

Equivalent of Data.Char.isLower in Haskell.

Mnemonic: Is Lower

IM

Equivalent of Data.Char.isNumber in Haskell.

Mnemonic: Is N-1=Mumber

IN

Equivalent of Data.Maybe.isNothing in Haskell.

Mnemonic: Is Nothing

IP

Equivalent of Data.Char.isPunctuation in Haskell.

Mnemonic: Is Puncuation

IR

Equivalent of System.IO.interact in Haskell.

Mnemonic: InteRact

IS

Equivalent of Data.Char.isSpace in Haskell.

Mnemonic: Is Space

IU

Equivalent of Data.Char.isUpper in Haskell.

Mnemonic: Is Upper

LA

Equivalent of Data.List.last in Haskell.

Mnemonic: LAst

LC

Equivalent of Prelude.lcm in Haskell.

Mnemonic: Least Common multiple

LG

Equivalent of Prelude.log in Haskell.

Mnemonic: LoGarithm

LI

Equivalent of Data.String.lines in Haskell.

Mnemonic: LInes

LM

Equivalent of Control.Monad.liftM in Haskell.

Mnemonic: Lift Monad

LN

Equivalent of Control.Monad.liftM2 in Haskell.

Mnemonic: Lift M+1=Nonad

LO

Equivalent of Control.Monad.liftM3 in Haskell.

Mnemonic: Lift M+2=Oonad

LU

Equivalent of Data.List.lookup in Haskell.

Mnemonic: LookUp

LV

Unsafe version of Data.List.lookup. Returns undefined if no value is found.

Mnemonic: LookU+1=Vp

Haskell implementation of this function:

import Data.List

LV :: Eq a => a -> [(a, b)] -> b
LV k m =
    case lookup k m of
        Just b -> b
        _      -> undefined

MI

Works like Data.List.map, but instead takes a function that has the element as the first argument and the element's index in the list as its second argument.

Mnemonic: Map with Indices

Haskell implementation of this function:

MI :: Integral i => (a -> i -> b) -> [a] -> [b]
MI f xs = zipWith f xs [0..]

NE

Equivalent of Data.Foldable.notElem in Haskell.

Mnemonic: Not Element of

OD

Equivalent of Prelude.odd in Haskell.

Mnemonic: ODd

PD

Equivalent of Prelude.pred in Haskell.

Mnemonic: PreDecessor

PI

Equivalent of Prelude.pi in Haskell.

Mnemonic: pi

PN

Takes in an integer and returns a boolean indicating whether or not the integer is a positive prime number.

Mnemonic: is a Prime Number

Haskell implementation of this function:

PN :: Integral i => i -> Bool
PN n = n > 1 && all ((/= 0).(n `mod`)) [2..n `div` 2]

PR

A list of positive integers representing all prime numbers, in order.

Mnemonic: PRimes

Haskell implementation of this function:

PR :: Integral i => [i]
PR = 2:3:prs
    where
        1:p:candidates = [6 * k + r | k <- [0..], r <- [1, 5]]
        prs            = p : filter isPrime candidates
        isPrime n      = all (not . divides n)
                             $ takeWhile (\p' -> p' * p' <= n) prs
        divides n p''  = n `mod` p'' == 0

PS

Equivalent of System.IO.putStrLn in Haskell.

Mnemonic: Put String line

PT

Equivalent of System.IO.putStr in Haskell.

Mnemonic: Put sTring line

QT

Equivalent of Prelude.quot in Haskell.

Mnemonic: QuoTient

RC

Equivalent of Data.List.genericReplicate in Haskell.

Mnemonic: RepliCate

RF

Equivalent of System.IO.readFile in Haskell.

Mnemonic: Read File

RM

Equivalent of Prelude.rem in Haskell.

Mnemonic: ReMainder

RP

Equivalent of Data.List.repeat in Haskell.

Mnemonic: RePeat

RT

Equivalent of Control.Monad.return in Haskell.

Mnemonic: ReTurn

SC

Equivalent of Control.Arrow.second in Haskell.

Mnemonic: SeCond

SD

Equivalent of Data.Tuple.snd in Haskell.

Mnemonic: SeconD

SI

Equivalent of Prelude.sin in Haskell.

Mnemonic: SIne

SL

Equivalent of Data.List.scanl1 in Haskell.

Mnemonic: Scan Left 1

SN

Equivalent of Data.List.span in Haskell.

Mnemonic: SpaN

SP

Equivalent of Data.List.genericSplitAt in Haskell.

Mnemonic: generic SPlit at

SQ

Equivalent of Control.Monad.sequence in Haskell.

Mnemonic: SeQuence

SR

Equivalent of Data.List.scanr in Haskell.

Mnemonic: Scan Right

SS

Equivalent of Data.List.scanr1 in Haskell.

Mnemonic: Scan R+1=Sight 1

ST

Equivalent of Prelude.sqrt in Haskell.

Mnemonic: Square rooT

SU

Equivalent of Prelude.succ in Haskell.

Mnemonic: SUccessor

TA

Equivalent of Prelude.tan in Haskell.

Mnemonic: TAngent

TL

Equivalent of Data.Char.toLower in Haskell.

Mnemonic: To Lower

TR

Equivalent of Prelude.True in Haskell.

Mnemonic: TRue

TU

Equivalent of Data.Char.toUpper in Haskell.

Mnemonic: To Upper

UC

Equivalent of Data.Tuple.uncurry in Haskell.

Mnemonic: UnCurry

UD

Equivalent of Prelude.undefined in Haskell.

Mnemonic: UnDefined

UL

Equivalent of Data.String.unlines in Haskell.

Mnemonic: UnLines

UT

Equivalent of Prelude.until in Haskell.

Mnemonic: UnTil

UW

Equivalent of Data.String.unwords in Haskell.

Mnemonic: UnWords

UZ

Equivalent of Data.List.unzip in Haskell.

Mnemonic: UnZip

WF

Equivalent of System.IO.writeFile in Haskell.

Mnemonic: Write File

WO

Equivalent of Data.String.words in Haskell.

Mnemonic: WOrds

ZT

Equivalent of Data.List.zip3 in Haskell.

Mnemonic: Zip Three

ZU

Equivalent of Data.List.unzip3 in Haskell.

Mnemonic: unZip T+1=Uhree

ZW

Equivalent of Data.List.zipWith3 in Haskell.

Mnemonic: Zip With 3