• Stars
    star
    193
  • Rank 201,081 (Top 4 %)
  • Language
    Haskell
  • License
    BSD 3-Clause "New...
  • Created over 5 years ago
  • Updated over 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Dynamic typing in Haskell

dynamic

Finally, dynamically typed programming in Haskell made easy!

Introduction

Tired of making data types in your Haskell programs just to read and manipulate basic JSON/CSV files? Tired of writing imports? Use dynamic, dynamically typed programming for Haskell!

Load it up

Launch ghci, the interactive REPL for Haskell.

import Dynamic

Don't forget to enable OverloadedStrings:

:set -XOverloadedStrings

Now you're ready for dynamicness!

The Dynamic type

In the dynamic package there is one type: Dynamic!

What, you were expecting something more? Guffaw!

Make dynamic values as easy as pie!

Primitive values are easy via regular literals:

> 1
1
> "Hello, World!"
"Hello, World!"

Arrays and objects have handy functions to make them:

> fromList [1,2]
[
    1,
    2
]
> fromDict [ ("k", 1), ("v", 2) ]
{
    "k": 1,
    "v": 2
}

Get object keys or array or string indexes via !:

> fromDict [ ("k", 1), ("v", 2) ] ! "k"
1
> fromList [1,2] ! 1
2
> "foo" ! 2
"o"

Web requests!

> chris <- getJson "https://api.github.com/users/chrisdone" []
> chris
{
    "bio": null,
    "email": null,
    "public_gists": 176,
    "repos_url": "https://api.github.com/users/chrisdone/repos",
    "node_id": "MDQ6VXNlcjExMDE5",
    "following_url": "https://api.github.com/users/chrisdone/following{/other_user}",
    "location": "England",
    "url": "https://api.github.com/users/chrisdone",
    "gravatar_id": "",
    "blog": "https://chrisdone.com",
    "gists_url": "https://api.github.com/users/chrisdone/gists{/gist_id}",
    "following": 0,
    "hireable": null,
    "organizations_url": "https://api.github.com/users/chrisdone/orgs",
    "subscriptions_url": "https://api.github.com/users/chrisdone/subscriptions",
    "name": "Chris Done",
    "company": "FP Complete @fpco ",
    "updated_at": "2019-02-22T11:11:18Z",
    "created_at": "2008-05-21T10:29:09Z",
    "followers": 1095,
    "id": 11019,
    "public_repos": 144,
    "avatar_url": "https://avatars3.githubusercontent.com/u/11019?v=4",
    "type": "User",
    "events_url": "https://api.github.com/users/chrisdone/events{/privacy}",
    "starred_url": "https://api.github.com/users/chrisdone/starred{/owner}{/repo}",
    "login": "chrisdone",
    "received_events_url": "https://api.github.com/users/chrisdone/received_events",
    "site_admin": false,
    "html_url": "https://github.com/chrisdone",
    "followers_url": "https://api.github.com/users/chrisdone/followers"
}

Trivially read CSV files!

> fromCsvNamed "name,age,alive,partner\nabc,123,true,null\nabc,ok,true,true"
[{
    "alive": true,
    "age": 123,
    "partner": null,
    "name": "abc"
},{
    "alive": true,
    "age": "ok",
    "partner": true,
    "name": "abc"
}]

Dynamically typed programming!

Just write code like you do in Python or JavaScript:

> if chris!"followers" > 500 then chris!"public_gists" * 5 else chris!"name"
880

Experience the wonders of dynamic type errors!

Try to treat non-numbers as numbers and you get the expected result:

> map (\o -> o ! "age" * 2) $ fromCsvNamed "name,age,alive,partner\nabc,123,true,null\nabc,ok,true,true"
[246,*** Exception: DynamicTypeError "Couldn't treat string as number: ok"

Laziness makes everything better!

> map (*2) $ toList $ fromJson "[\"1\",true,123]"
[2,*** Exception: DynamicTypeError "Can't treat bool as number."

Woops...

> map (*2) $ toList $ fromJson "[\"1\",123]"
[2,246]

That's better!

Heterogenous lists are what life is about:

> toCsv [ 1, "Chris" ]
"1.0\r\nChris\r\n"

I can't handle it!!!

Modifying and updating records

Use modify or set to massage data into something more palatable.

> modify "followers" (*20) chris
{
    "bio": null,
    "email": null,
    "public_gists": 176,
    "repos_url": "https://api.github.com/users/chrisdone/repos",
    "node_id": "MDQ6VXNlcjExMDE5",
    "following_url": "https://api.github.com/users/chrisdone/following{/other_user}",
    "location": "England",
    "url": "https://api.github.com/users/chrisdone",
    "gravatar_id": "",
    "blog": "https://chrisdone.com",
    "gists_url": "https://api.github.com/users/chrisdone/gists{/gist_id}",
    "following": 0,
    "hireable": null,
    "organizations_url": "https://api.github.com/users/chrisdone/orgs",
    "subscriptions_url": "https://api.github.com/users/chrisdone/subscriptions",
    "name": "Chris Done",
    "company": "FP Complete @fpco ",
    "updated_at": "2019-02-22T11:11:18Z",
    "created_at": "2008-05-21T10:29:09Z",
    "followers": 21900,
    "id": 11019,
    "public_repos": 144,
    "avatar_url": "https://avatars3.githubusercontent.com/u/11019?v=4",
    "type": "User",
    "events_url": "https://api.github.com/users/chrisdone/events{/privacy}",
    "starred_url": "https://api.github.com/users/chrisdone/starred{/owner}{/repo}",
    "login": "chrisdone",
    "received_events_url": "https://api.github.com/users/chrisdone/received_events",
    "site_admin": false,
    "html_url": "https://github.com/chrisdone",
    "followers_url":
    "https://api.github.com/users/chrisdone/followers"
}

List of numbers?

The answer is: Yes, Haskell can do that!

> [1.. 5] :: [Dynamic]
[1,2,3,4,5]

Append things together

Like in JavaScript, we try to do our best to make something out of appending...

> "Wat" <> 1 <> "!" <> Null
"Wat1!"

Suspicious?

It's real! This code runs just fine:

silly a =
  if a > 0
     then toJsonFile "out.txt" "Hi"
     else toJsonFile "out.txt" (5 + "a")

That passes the dynamic typing test.

Mix and match your regular Haskell functions

Here's an exporation of my Monzo (bank account) data.

Load up the JSON output:

> monzo <- fromJsonFile "monzo.json"

Preview what's in it:

> take 100 $ show monzo
"{\n    \"transactions\": [\n        {\n            \"amount\": 10000,\n            \"dedupe_id\": \"com.monzo.f"
> toKeys monzo
["transactions"]

OK, just transactions. How many?

> length $ toList $ monzo!"transactions"
119

What keys do I get in each transaction?

> toKeys $ head $ toList $ monzo!"transactions"
["amount","dedupe_id","attachments","can_be_made_subscription","fees","created","category","settled","can_split_the_bill","can_add_to_tab","originator","currency","include_in_spending","merchant","can_be_excluded_from_breakdown","international","counterparty","scheme","local_currency","metadata","id","labels","updated","account_balance","is_load","account_id","notes","user_id","local_amount","description"]

What's in amount?

> (!"amount") $ head $ toList $ monzo!"transactions"
10000

Looks like pennies, let's divide that by 100. What's the total +/- sum of my last 5 transactions?

> sum $ map ((/100) . (!"amount")) $ take 5 $ toList $ monzo!"transactions"
468.65

What categories are there?

> nub $ map (!"category") $ toList $ monzo!"transactions"
["general","entertainment","groceries","eating_out","shopping","expenses","bills","personal_care","cash"]

How many transactions did I do in each category? Let's use Data.Map to histogram that.

> fromDict $ M.toList $ foldl (\cats cat -> M.insertWith (+) cat 1 cats) mempty $ map (!"category") $ toList $ monzo!"transactions"
{
    "personal_care": 2,
    "entertainment": 8,
    "bills": 3,
    "general": 58,
    "groceries": 16,
    "shopping": 8,
    "expenses": 19,
    "eating_out": 4,
    "cash": 1
}
>

Cool!

More Repositories

1

elisp-guide

A quick guide to Emacs Lisp programming
1,397
star
2

intero

Haskell
1,021
star
3

jquery-console

A simple JQuery console emulator
JavaScript
668
star
4

hell

Haskell-based shell scripting language
Haskell
520
star
5

jl

Functional sed for JSON
Haskell
473
star
6

lucid

Clear to write, read and edit DSL for writing HTML
Haskell
284
star
7

vado

A demo web browser engine written in Haskell
Haskell
281
star
8

z

A strict, impure, curried, partially applied programming language with rather peculiar syntax.
Haskell
277
star
9

duet

A tiny language, a subset of Haskell aimed at aiding teachers teach Haskell
Haskell
201
star
10

tryhaskell

Try Haskell
Haskell
187
star
11

hulk

Haskell IRC daemon.
Haskell
142
star
12

emacs-config

My Emacs config
Emacs Lisp
118
star
13

haskell-style-guide

95
star
14

ircbrowse

An IRC analysis server.
Haskell
80
star
15

purify

Reproducible builds for PureScript
Haskell
73
star
16

labels

Declare and access tuple fields with labels
Haskell
61
star
17

descriptive

Self-describing consumers/parsers
Haskell
41
star
18

ghci-reload-demo

A demo of using GHCi as a persistent development environment
Haskell
41
star
19

chrisdone-xmonad

My xmonad configuration.
Haskell
33
star
20

freenect

Haskell interface to Kinect.
Haskell
26
star
21

bdo

Do things in the browser from Emacs, namely update the stylesheet (but maybe more later)
Haskell
26
star
22

ats-examples

Examples from Introduction to Programming in ATS
ATS
25
star
23

present

Make presentations for data types
Haskell
25
star
24

audit

Code auditing mode for Emacs
Emacs Lisp
25
star
25

webshow

Show programming language printed values in a web UI
Haskell
22
star
26

sdl2-sprite

Create and animate sprites easily with sdl2 (Haskell)
Haskell
22
star
27

prana

Interpreter for GHC Haskell
Haskell
22
star
28

flycheck-stack

A flycheck checker that uses stack ghci
Emacs Lisp
22
star
29

ini

Quick and easy INI configuration files for Haskell
Haskell
22
star
30

zenburn

Fork of Zenburn theme for emacs
Emacs Lisp
20
star
31

inflex

Pure, statically typed, content-addressable, programming language for spreadsheet use
Haskell
20
star
32

ghc-server

A server interface to GHC.
Haskell
20
star
33

advent-2017-maze-rust-haskell

Haskell
17
star
34

google-closure-purescript

Dockerfile
16
star
35

streaming-parsers

Streaming parsers collection
Haskell
15
star
36

ace

Attempto Controlled English parser and printer
Haskell
15
star
37

scrobble

Scrobbling server. A library providing server-side and client-side support for the Audioscrobbler Realtime Submission protocol: http://www.audioscrobbler.net/development/protocol/
Haskell
15
star
38

flo

Generate flow charts from your code base.
Haskell
14
star
39

conditions

Conditions for Haskell
Haskell
14
star
40

pgsql-simple

A mid-level client library for the PostgreSQL database, intended to be fast and easy to use.
Haskell
13
star
41

sandbox

Small random demonstrations of code
Haskell
12
star
42

duta

Haskell
12
star
43

pure-io

Pure IO monad.
Haskell
11
star
44

caseof

A simple way to query constructors, like cases but slightly more concise
Haskell
11
star
45

css

Monadic Haskell DSL for CSS.
Haskell
10
star
46

rocksdb-haskell-ng

Haskell
9
star
47

snappy

A reactive library for using SVG in the browser for Haskell
Haskell
9
star
48

display

Haskell
8
star
49

ety

Simple API for etymology online
Haskell
8
star
50

copy-paste-sync

An easy way to share clipboard (not encrypted) on a trusted LAN
Haskell
8
star
51

tdiff

Simply print the time difference between lines from stdin
Haskell
8
star
52

frisby

Linear time composable parser for PEG grammars
Haskell
7
star
53

forge

Haskell form library
Haskell
7
star
54

asp-mode

A simple ASP mode for Emacs which does syntax highlighting and indentation support
Emacs Lisp
7
star
55

basic-lens

Basic lens type and functions
Haskell
6
star
56

number

Emacs number manipulation
Emacs Lisp
6
star
57

osdkeys

Show keys pressed with an on-screen display (Linux only)
Haskell
6
star
58

emacs-magit-config

Handy pre-made Emacs config for using magit
Emacs Lisp
6
star
59

org-focus

Emacs Lisp
6
star
60

haskell-exercises

Haskell training test suite
Haskell
6
star
61

gmail

GMail client for Emacs
Emacs Lisp
6
star
62

maintainer

Haskell
5
star
63

hex-server

A minimal X11 server written in Haskell
Haskell
5
star
64

cabal-sign

Haskell
5
star
65

blogination

Very simple blog software
Haskell
5
star
66

sorting

Sorting algorithms
Haskell
4
star
67

stack-doc

Show stack's documentation in Emacs
Emacs Lisp
4
star
68

fore

Haskell Core to JavaScript compiler
Haskell
4
star
69

cron-daemon

Run a program as a daemon
Haskell
4
star
70

keyboard-stats

Gather and produce statistics about keyboard typing habbits
Haskell
4
star
71

codeparty

Online code sharing teaching platform
JavaScript
4
star
72

pdfinfo

Simple pdfinfo wrapper
Haskell
4
star
73

haskelldb-demo

Haskell
4
star
74

hog

IRC logger bot
Haskell
3
star
75

clockin

Track clocking in and out of work.
Haskell
3
star
76

sourcemap

Implementation of source maps as proposed by Mozilla and Google
Haskell
3
star
77

proclog

Haskell
3
star
78

haskell-trace

Add tracing to modules.
Haskell
2
star
79

hamlet-mode

Emacs Lisp
2
star
80

pid1-rust

Rust
2
star
81

senza

An interface to blaze-html without the need for operators.
Haskell
2
star
82

env-args

Source program arguments from the environment in a predictable way
Haskell
2
star
83

url-generic

Parse/format generic key/value URLs from record data types.
Haskell
2
star
84

typegraph

Haskell
1
star
85

riker

Simple reverse proxy, replacement for nginx
Haskell
1
star
86

servant-example

Haskell
1
star
87

liquid-post

Haskell
1
star
88

terminal

Haskell
1
star
89

snap-app

Small snap modules for MVC.
Haskell
1
star
90

yesod-lucid

Haskell
1
star
91

novella

Haskell
1
star
92

codepad

Haskell library for pasting to CodePad
Haskell
1
star