Skip to content

Commit dd01f71

Browse files
committed
haskell: Add Haskell binding
1 parent 3f58e6f commit dd01f71

File tree

18 files changed

+703
-1
lines changed

18 files changed

+703
-1
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ BINDINGS := \
66
crystal \
77
csharp \
88
go \
9+
haskell \
910
java \
1011
julia \
1112
lua \
@@ -27,6 +28,7 @@ DIRS := \
2728
BUILD-DIRS := \
2829
libys \
2930
go \
31+
haskell \
3032
nodejs \
3133
python \
3234
ruby \

doc/bindings.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Currently there are working libraries for:
4343
* [Clojure](https://clojars.org/org.yamlscript/clj-yamlscript)
4444
* [Crystal](https://shardbox.org/shards/yamlscript)
4545
* [Go](https://github.com/yaml/yamlscript-go)
46+
* [Haskell](https://hackage.haskell.org/package/yamlscript)
4647
* [Java](https://clojars.org/org.yamlscript/yamlscript)
4748
* [Julia](https://juliahub.com/ui/Packages/General/YAMLScript)
4849
* [Lua](https://luarocks.org/modules/ingy/yamlscript)

doc/examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ This page contains a links to programs written in YS.
4242
* [util/release-yamlscript](
4343
https://github.com/yaml/yamlscript/blob/main/util/release-yamlscript)
4444
The utility that orchestrates the release of YS; including `ys`, libys.so`
45-
and `libys.so` bindings for 13 programming languages.
45+
and `libys.so` bindings for 15 programming languages.
4646
* [util/brew-update](
4747
https://github.com/yaml/yamlscript/blob/main/util/brew-update)
4848
The utility that updates the Homebrew formula for YS.

doc/install.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ languages:
115115
* [Clojure](https://clojars.org/org.yamlscript/clj-yamlscript)
116116
* [Crystal](https://shardbox.org/shards/yamlscript)
117117
* [Go](https://github.com/yaml/yamlscript-go)
118+
* [Haskell](https://hackage.haskell.org/package/yamlscript)
118119
* [Java](https://clojars.org/org.yamlscript/yamlscript)
119120
* [Julia](https://juliahub.com/ui/Packages/General/YAMLScript)
120121
* [Lua](https://luarocks.org/modules/ingy/yamlscript)

doc/loaders.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ The following loader libraries are currently available:
2020
* [Clojure](https://clojars.org/org.yamlscript/clj-yamlscript)
2121
* [Crystal](https://shardbox.org/shards/yamlscript)
2222
* [Go](https://github.com/yaml/yamlscript-go)
23+
* [Haskell](https://hackage.haskell.org/package/yamlscript)
2324
* [Java](https://clojars.org/org.yamlscript/yamlscript)
2425
* [Julia](https://juliahub.com/ui/Packages/General/YAMLScript)
2526
* [Lua](https://luarocks.org/modules/ingy/yamlscript)

haskell/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/cabal.project.local
2+
/dist-newstyle/
3+
/License
4+
/libys/
5+
/yamlscript.cabal

haskell/Makefile

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
include ../common/base.mk
2+
include $(COMMON)/binding.mk
3+
GHC-VERSION := 9.12.1
4+
include $(MAKES)/cabal.mk # includes ghc.mk
5+
include $(MAKES)/shell.mk
6+
7+
CABAL-INDEX := $(CABAL_DIR)/packages/hackage.haskell.org/01-index.tar.gz
8+
9+
ifneq (,$(shell command -v ys))
10+
ifneq (,$(wildcard ~/.yamlscript-secrets.yaml))
11+
HACKAGE-TOKEN := \
12+
$(shell ys -e '.hackage.token:say' ~/.yamlscript-secrets.yaml)
13+
endif
14+
endif
15+
16+
HASKELL-DIST := \
17+
dist-newstyle/sdist/yamlscript-$(YAMLSCRIPT_VERSION).0.tar.gz
18+
19+
HASKELL-DEPS := \
20+
$(GHC) \
21+
$(CABAL) \
22+
$(CABAL-INDEX) \
23+
yamlscript.cabal \
24+
License \
25+
26+
LIBYS := /tmp/libys
27+
28+
#------------------------------------------------------------------------------
29+
build:: build-doc
30+
31+
build-doc:: ReadMe.md
32+
33+
test:: test-cabal test-ffi
34+
35+
test-cabal: $(HASKELL-DEPS) $(LIBYS)
36+
cabal test --test-show-details=direct
37+
38+
test-ffi: $(HASKELL-DEPS) $(LIBYS)
39+
cabal run yamlscript-test -- \
40+
-c 'import YAMLScript; \
41+
print =<< loadYAMLScript "inc: 41"' && \
42+
cabal run yamlscript-test -- \
43+
-c 'import YAMLScript; \
44+
print =<< loadYAMLScript "!YS-v0\ninc: 41"'
45+
46+
pkg-test: $(HASKELL-DEPS)
47+
$(MAKE) clean
48+
$(MAKE) test
49+
cabal sdist
50+
cabal exec -- cabal install $(HASKELL-DIST)
51+
52+
ls: dist
53+
ls -l $(HASKELL-DIST)
54+
55+
release: dist
56+
ifndef HACKAGE-TOKEN
57+
@echo "HACKAGE-TOKEN is not set"
58+
@exit 1
59+
endif
60+
cabal upload \
61+
--publish \
62+
--verbose \
63+
--token='$(HACKAGE-TOKEN)' \
64+
$(HASKELL-DIST)
65+
66+
check: $(HASKELL-DEPS)
67+
cabal $@
68+
69+
dist: $(HASKELL-DEPS)
70+
cabal check
71+
cabal sdist
72+
73+
clean::
74+
$(RM) yamlscript.cabal License
75+
$(RM) -r dist-newstyle/ $(LIBYS)
76+
77+
$(CABAL-INDEX): $(CABAL)
78+
cabal update
79+
80+
yamlscript.cabal: cabal.ys $(YS)
81+
ys $< > $@
82+
83+
License: ../License
84+
cp $< $@
85+
86+
$(LIBYS): $(LIBYS-SO-FQNP)
87+
mkdir -p $(LIBYS)
88+
cp -r ../libys/lib $(LIBYS)/

haskell/ReadMe.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
<!-- DO NOT EDIT — THIS FILE WAS GENERATED -->
2+
3+
YS / YAMLScript
4+
===============
5+
6+
Add Logic to Your YAML Files
7+
8+
9+
## Synopsis
10+
11+
Load `file.yaml` with YS:
12+
13+
```yaml
14+
!YS-v0:
15+
16+
# Get data from external sources:
17+
names-url =:
18+
'github:dominictarr/random-name/first-names.json'
19+
20+
name-list =: names-url:curl:json/load
21+
22+
# Data object with literal keys and generated values:
23+
name:: name-list:shuffle:first
24+
aka:: name-list:rand-nth
25+
age:: &num 2 * 3 * 7
26+
color:: &hue
27+
rand-nth: qw(red green blue yellow)
28+
title:: "$(*num) shades of $(*hue)."
29+
```
30+
31+
and get:
32+
```json
33+
{
34+
"name": "Dolores",
35+
"aka": "Anita",
36+
"age": 42,
37+
"color": "green",
38+
"title": "42 shades of green."
39+
}
40+
```
41+
42+
43+
## Description
44+
45+
[YS](https://yamlscript.org) is a functional programming language with a clean
46+
YAML syntax.
47+
48+
YS can be used for enhancing ordinary [YAML](https://yaml.org) files with
49+
functional operations, such as:
50+
51+
* Import (parts of) other YAML files to any node
52+
* String interpolation including function calls
53+
* Data transforms including ones defined by you
54+
55+
This YS library should be a drop-in replacement for your current YAML loader!
56+
57+
Most existing YAML files are already valid YS files.
58+
This means that YS works as a normal YAML loader, but can also evaluate
59+
functional expressions if asked to.
60+
61+
Under the hood, YS code compiles to the Clojure programming language.
62+
This makes YS a complete functional programming language right out of the box.
63+
64+
Even though YS compiles to Clojure, and Clojure compiles to Java, there is no
65+
dependency on Java or the JVM.
66+
YS is compiled to a native shared library (`libys.so`) that can be used
67+
by any programming language that can load shared libraries.
68+
69+
To see the Clojure code that YS compiles to, you can use the YS
70+
CLI binary `ys` to run:
71+
72+
```text
73+
$ ys --compile file.ys
74+
(let
75+
[names-url "https://raw.githubusercontent.com/dominictarr/random-name/master/first-names.json"
76+
name-list (json/load (curl names-url))]
77+
(%
78+
"name" (first (shuffle name-list))
79+
"aka" (rand-nth name-list)
80+
"age" (_& 'num (mul+ 2 3 7))
81+
"color" (_& 'hue (rand-nth (qw red green blue yellow)))
82+
"title" (str (_** 'num) " shades of " (_** 'hue) ".")))
83+
```
84+
85+
## Haskell Usage
86+
87+
File `prog.hs`:
88+
89+
```haskell
90+
import YAMLScript
91+
import qualified Data.Text as T
92+
93+
main :: IO ()
94+
main = do
95+
let input = T.pack "inc: 41"
96+
result <- loadYAMLScript input
97+
print result
98+
```
99+
100+
File `file.ys`:
101+
102+
```yaml
103+
!YS-v0:
104+
105+
name =: "World"
106+
107+
foo: [1, 2, ! inc(41)]
108+
bar:: load("other.yaml")
109+
baz:: "Hello, $name!"
110+
```
111+
112+
File `other.yaml`:
113+
114+
```yaml
115+
oh: Hello
116+
```
117+
118+
Run:
119+
120+
```text
121+
$ runhaskell prog.hs
122+
Number 42.0
123+
```
124+
125+
## Installation
126+
127+
You can install this package using Cabal:
128+
129+
```bash
130+
cabal install yamlscript
131+
```
132+
133+
but you will need to have a system install of `libys.so`.
134+
135+
One simple way to do that is with:
136+
137+
```bash
138+
curl https://yamlscript.org/install | bash
139+
```
140+
141+
> Note: The above command will install the latest version of the YAMLScript
142+
command line utility, `ys`, and the shared library, `libys.so`, into
143+
`~/local/bin` and `~/.local/lib` respectively.
144+
145+
See <https://yamlscript.org/doc/install/> for more info.
146+
147+
## API Reference
148+
149+
### `loadYAMLScript :: MonadIO m => Text -> m Aeson.Value`
150+
151+
Load and evaluate YAMLScript code from a string.
152+
Returns the result as a JSON Value.
153+
154+
### `loadYAMLScriptFile :: MonadIO m => FilePath -> m Aeson.Value`
155+
156+
Load and evaluate YAMLScript code from a file.
157+
Returns the result as a JSON Value.
158+
159+
### `loadYAMLScriptPure :: Text -> Aeson.Value`
160+
161+
Convenience function for pure contexts.
162+
Note: This uses unsafePerformIO and should be used carefully.
163+
164+
### `YAMLScriptError`
165+
166+
Error type for YAMLScript operations:
167+
- `YAMLScriptParseError String` - Parsing errors
168+
- `YAMLScriptRuntimeError String` - Runtime evaluation errors
169+
- `YAMLScriptFFIError String` - Foreign function interface errors
170+
171+
## See Also
172+
173+
* [YS Web Site](https://yamlscript.org)
174+
* [YS Blog](https://yamlscript.org/blog)
175+
* [YS Source Code](https://github.com/yaml/yamlscript)
176+
* [YS Samples](https://github.com/yaml/yamlscript/tree/main/sample)
177+
* [YS Programs](https://rosettacode.org/wiki/Category:YAMLScript)
178+
* [YAML](https://yaml.org)
179+
* [Clojure](https://clojure.org)
180+
181+
182+
## Authors
183+
184+
Ingy döt Net <[email protected]>
185+
186+
## License & Copyright
187+
188+
Copyright 2022-2025 Ingy döt Net <[email protected]>
189+
190+
This project is licensed under the terms of the `MIT` license.
191+
See [LICENSE](https://github.com/yaml/yamlscript/blob/main/License) for
192+
more details.

0 commit comments

Comments
 (0)