enso: Init repo
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Files
|
||||
*.org
|
||||
16
LICENSE
Normal file
16
LICENSE
Normal file
@ -0,0 +1,16 @@
|
||||
THE MUKYU PUBLIC LICENSE
|
||||
Draft 1, November 2010
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
THE MUKYU PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
1. This license document permits you to DO WHAT THE FUCK YOU WANT TO
|
||||
as long as you AGREE TO NOT STEAL BOOKS FROM PATCHOULI'S LIBRARY.
|
||||
|
||||
This program is distributed in the hope that it will be magical,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
USEFULNESS or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
27
README.md
Normal file
27
README.md
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
# Enso - The Minimalist IO Monad Library
|
||||
|
||||
Enso is a minimal IO Monad library that provides only absolute basics, nothing more and nothing less. It's not very robust, and that's by design. It's not amazing, and that's also by design. Enso is both something I wrote to learn how Monads (such as IO Monads) work in hopes to respark my interest in Functional Programming, as well as a utility built to make the development of my projects heavily utilizing the paradigm much easier.
|
||||
|
||||
As a result, Enso is not exactly fantastical and may not be for you, unless you don't mind the batteries not included mentality of Enso. Furthermore, I am not amazing at Functional Programming, and I have learned all of what I know about it through Haskell. As well, I'm not an academic of any sort (not a Computer Sciences major nor student) and thus this most likely is not the most impressive attempt at an IO Monad. I'm more of the engineer praxis type, and I just wanted to see whether I can even do the task.
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
Enso provides the IO Thunk in order to handle data and functions. Functions and any data made pure via `to_IO` are lazily evaluated and then able to be used on the spot or when necessary, with the `run` function intended to sugar the usage of functions stored this way. `flatmap`, `map`, `join`, and `lift` are also provided in order to be used with the IO Thunk or with any other potentially impure functions to be executed in the Monad's context. It's mostly bare bones other than that besides `readstr` to read from a UNIX file descriptor and `strput` to write a string to STDOUT.
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
Enso doesn't depend on anything but the Nim language itself. As such, Enso is meant to be a batteries not included library that provides niceties to make Functional Programming a little quicker, or at least I tell myself that as I really just designed this out of sheer curiosity.
|
||||
|
||||
|
||||
# Why should I use Enso?
|
||||
|
||||
The short answer, you shouldn't unless you are insane like I am.
|
||||
|
||||
The long answer is that maybe you're a lot like me and want to better understand how Functional Programming works under the hood for some reason, and you want to tinker around with building the systems yourself too. I also built Enso because the only Monad library I found for Nim is practically abandoned, and I was psychotic enough to start a project with an associate where we decided to use Functional Programming for it, but we had no good systems to use for IO that added a few bells and whistles for us. For all I know, Enso may get new code should we need more. I don't quite know yet.
|
||||
|
||||
If you like Enso, great. If you don't like Enso, great.
|
||||
|
||||
12
enso.nimble
Normal file
12
enso.nimble
Normal file
@ -0,0 +1,12 @@
|
||||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "buckwheat"
|
||||
description = "A minimalist IO Monad library in Nim"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 2.0.4"
|
||||
59
src/enso.nim
Normal file
59
src/enso.nim
Normal file
@ -0,0 +1,59 @@
|
||||
import std/sugar
|
||||
|
||||
# Declarations
|
||||
|
||||
type FileDesc* = enum STDIN, STDOUT, STDERR
|
||||
type IO*[T] = proc(): T
|
||||
|
||||
func flatmap*[T, U](io: IO[T], fn: T -> IO[U]): IO[U]
|
||||
func lift*(fn: proc(): void): IO[void]
|
||||
func lift*[T](fn: proc(): T): IO[T]
|
||||
func join*[T](io: IO[IO[T]]): IO[T]
|
||||
func map*[T, U](io: IO[seq[T]], fn: T -> U): IO[seq[U]]
|
||||
func readstr*(stream: FileDesc): IO[string]
|
||||
func run*[T](io: IO[T]): T
|
||||
func strput*(str: string): IO[void]
|
||||
func to_IO*[T](val: T): IO[T]
|
||||
|
||||
# Definitions
|
||||
|
||||
func flatmap*[T, U](io: IO[T], fn: T -> IO[U]): IO[U] = join(io.map(fn))
|
||||
|
||||
func lift*(fn: proc(): void): IO[void] =
|
||||
proc(): void = fn()
|
||||
|
||||
func lift*[T](fn: proc(): T): IO[T] =
|
||||
proc(): T = fn()
|
||||
|
||||
func join*[T](io: IO[IO[T]]): IO[T] = io.map(run)
|
||||
|
||||
func map*[T, U](io: IO[seq[T]], fn: T -> U): IO[seq[U]] =
|
||||
proc(): seq[U] =
|
||||
let list: seq[T] = io()
|
||||
|
||||
if list.len == 0:
|
||||
@[]
|
||||
else:
|
||||
let
|
||||
head: T = list[0]
|
||||
tail: seq[T] = list[1..^1]
|
||||
new: IO[seq[T]] = to_IO tail
|
||||
|
||||
@[fn(head)] & run new.map(fn)
|
||||
|
||||
func readstr*(stream: FileDesc): IO[string] =
|
||||
case stream:
|
||||
of STDIN:
|
||||
lift proc(): string = readLine(stdin)
|
||||
of STDOUT:
|
||||
lift proc(): string = readLine(stdout)
|
||||
of STDERR:
|
||||
lift proc(): string = readLine(stderr)
|
||||
|
||||
func run*[T](io: IO[T]): T = io()
|
||||
|
||||
func strput*(str: string): IO[void] =
|
||||
proc(): void = echo str
|
||||
|
||||
func to_IO*[T](val: T): IO[T] =
|
||||
proc(): T = val
|
||||
1
tests/config.nims
Normal file
1
tests/config.nims
Normal file
@ -0,0 +1 @@
|
||||
switch("path", "$projectDir/../src")
|
||||
34
tests/test.nim
Normal file
34
tests/test.nim
Normal file
@ -0,0 +1,34 @@
|
||||
import enso
|
||||
import std/strformat
|
||||
|
||||
proc unsafe_void(str: string) =
|
||||
echo str
|
||||
|
||||
proc unsafe_int(str: string): int =
|
||||
echo str
|
||||
result = 1
|
||||
|
||||
func add_two(x: int): int = x + 2
|
||||
|
||||
func main() =
|
||||
run strput("Hello from Enso!")
|
||||
|
||||
let
|
||||
out_void: IO[void] = lift do(): unsafe_void("void")
|
||||
out_int: IO[int] = lift proc(): int = unsafe_int("int")
|
||||
|
||||
out_void()
|
||||
run strput(fmt"{out_int()}")
|
||||
|
||||
let
|
||||
num_list: IO[seq[int]] = to_IO @[1, 2, 3, 4, 5]
|
||||
list_added: IO[seq[int]] = num_list.map(add_two)
|
||||
|
||||
run strput(fmt"{list_added()}")
|
||||
|
||||
run strput("Enter a string")
|
||||
let read: IO[string] = readstr(STDIN)
|
||||
run strput(read())
|
||||
|
||||
when isMainModule:
|
||||
main()
|
||||
Reference in New Issue
Block a user