normalcalc

From Esolang
Jump to navigation Jump to search
normalcalc
Paradigm(s) functional
Designed by User:Itoh Shimon
Appeared in 31 July 2024 (JST)
Computational class Turing complete
Major implementations Original
Influenced by Unlambda
Lazy K
brainfuck
File extension(s) .nc

Normalcalc, designed by User:Itoh Shimon in 25-26 November 2023 (JST) and appeared in 31 July 2024 (JST), is a purely functional esoteric programming language based on combinatory logic and monadic IO.

Syntax

<program> ::= "`" <value> <value>
<value> ::= "*" | "/" | "|" | "_" | "," | "." | <program>

Operators

Operator Description
` Function application operator
* Substitution function (the S combinator; takes three values and applies the result applying the first one to the third one, to the result applying the second one to the third one)
/ Constant function (the K combinator; takes two values and returns the first one)
| Bind function (also called flatMap; takes a monad and a function that takes a value in that monad and returns a monad, and returns a monad)
_ Return function (also called pure and unit; takes a value and returns a monad containing it)
, Input function (takes a value, discards it, and returns a monad containing an input byte)
. Output function (takes an output byte and returns a monad containing an empty tuple)
# Line comment

Other characters are ignored.

Specifications

  • Lazy evaluation (for fixed point combinators)
  • Functions are curried.
  • Normalcalc programs return a monad (also called procedure).
  • Bytes are represented as Church numerals.
  • Empty tuples are represented as identity functions (the I combinator; takes a value and returns it).

Examples

no-op

`_/

Equivalent Haskell pseudocode:

main = return const

cat (for a single character)

``|`,/.

Equivalent Haskell pseudocode:

main = (>>=) (read1byte const) write1byte

full:

-- builtin:
import System.IO
import qualified Data.ByteString as BS

read1byte :: a -> IO Integer
read1byte _ = do
  eof <- isEOF
  if eof
    then return 256
    else toInteger . BS.head <$> BS.hGet stdin 1

write1byte :: Integer -> IO ()
write1byte = BS.hPut stdout . BS.pack . (:[]) . fromIntegral

-- program:
main = (>>=) (read1byte const) write1byte

See also

Other combinatory logic languages that support IO actions:

External resources