From 0e4810dcfb132bf276a282e25b8523a4009ae08b Mon Sep 17 00:00:00 2001 From: Miguel Date: Sun, 17 Mar 2019 18:14:32 +0100 Subject: rename blog dir --- .../00010_Links-and-Literature/index.md | 17 ++ 00_blog/00040_Haskell/00020_GHC-Notes/index.md | 39 +++++ .../00030_Xmonad-contribution/index.md | 20 +++ 00_blog/00040_Haskell/00040_Graham-Scan/index.md | 128 +++++++++++++++ .../00040_Haskell/00065_Base64-Encoder/base64.cast | 146 +++++++++++++++++ .../00040_Haskell/00065_Base64-Encoder/index.md | 21 +++ .../00040_Haskell/00120_Lambda-Calculus/index.md | 39 +++++ .../00130_Calculator-on-Parsec-and-GTK/calc.png | Bin 0 -> 30318 bytes .../00130_Calculator-on-Parsec-and-GTK/index.md | 21 +++ .../00140_Minimalistic-SVG-Generator/index.md | 27 ++++ .../00140_Minimalistic-SVG-Generator/svg.png | Bin 0 -> 13130 bytes .../00150_Applicative-vs-Monadic-Parsing/index.md | 175 +++++++++++++++++++++ .../00_pandoc_colors/index.md | 20 +++ .../00_pandoc_colors/index_breezedark.html | 117 ++++++++++++++ .../00_pandoc_colors/index_espresso.html | 113 +++++++++++++ .../00_pandoc_colors/index_haddock.html | 109 +++++++++++++ .../00_pandoc_colors/index_kate.html | 117 ++++++++++++++ .../00_pandoc_colors/index_monochrome.html | 96 +++++++++++ .../00_pandoc_colors/index_pygments.html | 114 ++++++++++++++ .../00_pandoc_colors/index_tango.html | 113 +++++++++++++ .../00_pandoc_colors/index_zenburn.html | 113 +++++++++++++ .../00200_Estatico-Page-Maker/index.md | 63 ++++++++ .../index.md | 1 + 00_blog/00040_Haskell/index.md | 8 + 24 files changed, 1617 insertions(+) create mode 100644 00_blog/00040_Haskell/00010_Links-and-Literature/index.md create mode 100644 00_blog/00040_Haskell/00020_GHC-Notes/index.md create mode 100644 00_blog/00040_Haskell/00030_Xmonad-contribution/index.md create mode 100644 00_blog/00040_Haskell/00040_Graham-Scan/index.md create mode 100644 00_blog/00040_Haskell/00065_Base64-Encoder/base64.cast create mode 100644 00_blog/00040_Haskell/00065_Base64-Encoder/index.md create mode 100644 00_blog/00040_Haskell/00120_Lambda-Calculus/index.md create mode 100644 00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png create mode 100644 00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md create mode 100644 00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md create mode 100644 00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/svg.png create mode 100644 00_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html create mode 100644 00_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md create mode 100644 00_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md create mode 100644 00_blog/00040_Haskell/index.md (limited to '00_blog/00040_Haskell') diff --git a/00_blog/00040_Haskell/00010_Links-and-Literature/index.md b/00_blog/00040_Haskell/00010_Links-and-Literature/index.md new file mode 100644 index 0000000..999c574 --- /dev/null +++ b/00_blog/00040_Haskell/00010_Links-and-Literature/index.md @@ -0,0 +1,17 @@ +# Haskell - Books, Links and Papers + +A growing collection of external links and books concerning Haskell. + +* **Learn You a Haskell** for Great Good by Marian Lipovaca +* **Real World Haskell** by Bryan O'Sullivan, Don Stewart, and John Goerzen +* **Parallel and Concurrent Programming in Haskell** by Simon Marlow +* **Haskell Wiki** +* **UPENN CIS 194** +* **What I Wish I Knew When Learning Haskell** by Stephen Diehl +* **Data61 Course** +* **Monads for functional programming (paper)** by Philip Wadler +* **Functional Pearl (paper)** +* **Why Functional Programming Matters (paper)** +* **Mailing Lists** +* **IRC** #haskell at chat.freenode.at +* **Monadic Warsaw** diff --git a/00_blog/00040_Haskell/00020_GHC-Notes/index.md b/00_blog/00040_Haskell/00020_GHC-Notes/index.md new file mode 100644 index 0000000..c945319 --- /dev/null +++ b/00_blog/00040_Haskell/00020_GHC-Notes/index.md @@ -0,0 +1,39 @@ +# The Glasgow Haskell Compiler + +## Some GHC Flags + + -v verbose mode + -O2 level 2 optimizations + -rtsopts allow +RTS flags + -prof enable basic time and allocation profiling + -auto-all cost centers on all top level functions + (you can also add them via the SCC pragma) + -caf-all generate data for CAFs (constant applicative forms) + -fforce-recomp force recompilation + -threaded Use threaed runtime + -eventlog enables +RTS -l flag + + -Wall + -Werror + + Notes: you will obtain the profiling versions of dependancies via: + stack install --profile [libraryname] + + -fprof-auto replaced -auto-all + -fprof-cafs replaced -caf-all + +## Some +RTS flags + + -K set stack limit + -s statistic reporting + -p profiling + -hc extract heap profile + -hy allocation by type + -hd allocation by constructor + -ix x is sampling frequency in seconds. e.g. 0.01) + -Nx x is number of cores to utilize + -l emit log file (can be used threadscope) + -ddump-simpl generate core + + Note: render the heap profile as graph with: hp2ps -e8in -c file.hp + show eventlog with: threadscope file.eventlog diff --git a/00_blog/00040_Haskell/00030_Xmonad-contribution/index.md b/00_blog/00040_Haskell/00030_Xmonad-contribution/index.md new file mode 100644 index 0000000..1a5bf0f --- /dev/null +++ b/00_blog/00040_Haskell/00030_Xmonad-contribution/index.md @@ -0,0 +1,20 @@ + April 2018 +# Pretty printer for empty visible workspaces + +My little contribution to **xmonad-contrib**, adding functionality to the +marvelous xmonad tiling window manager, I love and use since a couple of +years. + +## Description + +Simple extensions of the pretty printer to differentiate between empty and non-empty visible workspaces. Analogical to the existing functionality for hidden workspaces. Particularly useful if some displays managed by xmonad are turned off temporarily. + +The new 'ppVisibleNoWindows' function was wrapped in a Maybe data type. Its value dafaults to 'Nothing' and 'ppVisible' is used as fallback. + +## Motivation + +My TV is often turned off. Still I want to know if its workspace contains any windows, without having to switch workspaces. + +## Github Link +| _Xmonad-Contrib: Added pretty printer for empty visible workspaces (wrapped in Maybe)_ +| diff --git a/00_blog/00040_Haskell/00040_Graham-Scan/index.md b/00_blog/00040_Haskell/00040_Graham-Scan/index.md new file mode 100644 index 0000000..195dbe1 --- /dev/null +++ b/00_blog/00040_Haskell/00040_Graham-Scan/index.md @@ -0,0 +1,128 @@ +Haskell – Convex Hull – Graham Scan +=================================== + +December 16, 2017 + +Playing with Convex Hulls (via Graham Scan) and SVG Export in Haskell: + +This is an embedded SVG generated by the Haskell programm below: + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +--------------------------------------------------------------------------------------------- +-- +-- GRAHAM SCAN IMPLEMENTATION +-- +-- This little haskell programm calulates the Convex Hull for a set of 2D points. +-- It ships wit a main function that feeds the Graham Scan algorithm with some +-- random points and generates a simple SVG of the input points and resulting envelope. +-- A simple SVG encoder is included. +-- +-- Alogrithm used: https://en.wikipedia.org/wiki/Graham_scan +-- +-- CREDITS -- +-- +-- Michal Idziorek +-- 16 December 2017 +-- +--------------------------------------------------------------------------------------------- + +import Data.List +import System.Random + +--------------------------------------------------------------------------------------------- + +-- GRAHAM SCAN -- + +-- Three points are clockwise if ccw < 0. +ccw (p1x,p1y) (p2x,p2y) (p3x,p3y) = (p2x - p1x)*(p3y - p1y) - (p2y - p1y)*(p3x - p1x) + +-- Calculate the slope defined by 2 points. (return Infinity, if points are identical). +slope (ax,ay) (bx,by) | (ax,ay ) == (bx,by) = 1/0 -- Infinity + | otherwise = (bx-ax)/(by-ay) + +-- Comparison function to sort points counterclockwise (given a reference point). +slope_cmp a b c = compare (slope a c) (slope a b) + +-- Comparison function using the y and x coordinates for ordering. +graham_cmp (ax,ay) (bx,by) | ay /= by = compare ay by + | otherwise = compare ax bx + +-- Graham scan on prepared data. this will calculate the convex hull. +graham_calc [] hs = hs +graham_calc (x1:xs) hh | length(hh) < 2 = graham_calc xs (x1:hh) +graham_calc xx@(x1:xs) hh@(h1:h2:hs) | ccw x1 h1 h2 < 0 = graham_calc xs (x1:hh) + | otherwise = graham_calc xx (h2:hs) + +-- Find the starting point, sort all points counterclockwise and perform the graham scan. +graham xs = graham_calc sortedPoints [] + where minPoint = minimumBy graham_cmp xs + sortedPoints = sortBy (slope_cmp minPoint) xs + +--------------------------------------------------------------------------------------------- + +-- XML ENCODING-- + +xml_attr (x:xs) = x++"=\""++(head xs)++"\" " +xml_enc tag attrs body = "<"++tag++" "++xml_attrs++">"++body++"" + where xml_attrs = unlines $ map xml_attr attrs + +-- SVG ENCODING -- + +-- hardcoded scaling and panning function +svg_transf x = x*30+5 + +line_to_svg ((x1,y1),(x2,y2)) = xml_enc "line" [["x1",show lx1],["y1",show ly1], + ["x2",show lx2],["y2",show ly2], + ["style", "stroke:rgb(255,0,0);stroke-width:2"]] "" + where lx1=svg_transf x1 + lx2=svg_transf x2 + ly1=svg_transf y1 + ly2=svg_transf y2 + +point_to_svg (x,y) = xml_enc "circle" [["cx",show cx],["cy",show cy],["r","5"], + ["fill","rgb(30,150,"++(show (floor dist))++")"]] "" + where cx=svg_transf x + cy=svg_transf y + dist= (sqrt ((x-5)*(x-5) + (y-5)*(y-5)))*255/8 + + + +-- draws SVG points and lines (in hardcoded sizes and colors) +svg_draw p l = xml_enc "svg" [style,["width","330"],["height","330"]] body + where style = ["style", + "background-color:black;border:3px solid green;margin:2px;"] + body = (unlines (map point_to_svg p )) ++ + (unlines (map line_to_svg l )) + +-- calculate convex hull and generate svg +svg_graham xs = svg_draw xs (zip hull hull_open) + where hull_open = graham xs + hull = (last hull_open) : hull_open + +-- RANDOMIZING -- + +randomPoints g cnt = take cnt (zip r10a r10b) + where r5 = randomRs (0,5) g :: [Double] + r10a =zipWith (+) r5 (drop cnt r5) + r10b =zipWith (+) (drop (2*cnt) r5) (drop (3*cnt) r5) + +--------------------------------------------------------------------------------------------- + +-- MAIN -- + +-- Note that this is the only place of impurity in this source-file. +-- Is is subject to side effects due to I/O (we are writng to stdout) +-- and the random number generator. +main = do + g <- newStdGen + putStr (svg_graham (randomPoints g 25)) + putStr (svg_graham (randomPoints g 50)) + putStr (svg_graham (randomPoints g 100)) + putStr (svg_graham (randomPoints g 250)) + putStr (svg_graham (randomPoints g 500)) + putStr (svg_graham (randomPoints g 1500)) + +--------------------------------------------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/00_blog/00040_Haskell/00065_Base64-Encoder/base64.cast b/00_blog/00040_Haskell/00065_Base64-Encoder/base64.cast new file mode 100644 index 0000000..b32cd78 --- /dev/null +++ b/00_blog/00040_Haskell/00065_Base64-Encoder/base64.cast @@ -0,0 +1,146 @@ +{ + "env": { + "TERM": "screen-256color", + "SHELL": "/bin/bash" + }, + "version": 1, + "command": null, + "title": null, + "width": 90, + "height": 7, + "duration": 26.498611, + "stdout": [ + [ + 0.018948, + "miguel@megaloman:~/git/haskell/base64$ " + ], + [ + 0.831467, + "cat /tmp/random.bin | pv | ./base64 > /dev/null " + ], + [ + 0.269283, + "\r\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[17Pecho \"Hello Base64!\" | ./base64" + ], + [ + 1.242802, + "\r\n" + ], + [ + 0.002817, + "SGVsbG8gQmFzZTY0IQo=\r\n" + ], + [ + 0.000531, + "miguel@megaloman:~/git/haskell/base64$ " + ], + [ + 0.827791, + "echo \"Hello Base64!\" | ./base64" + ], + [ + 0.207417, + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bcat /tmp/random.bin | pv | ./base64 > /dev/null " + ], + [ + 0.963475, + "\r\n" + ], + [ + 1.002914, + " 434MiB 0:00:01 [ 434MiB/s] [ <=> ]\r" + ], + [ + 0.99997, + " 876MiB 0:00:02 [ 441MiB/s] [ <=> ]\r" + ], + [ + 1.000022, + "1.28GiB 0:00:03 [ 439MiB/s] [ <=> ]\r" + ], + [ + 1.000032, + "1.73GiB 0:00:04 [ 455MiB/s] [ <=> ]\r" + ], + [ + 0.999929, + "2.18GiB 0:00:05 [ 464MiB/s] [ <=> ]\r" + ], + [ + 0.999976, + "2.64GiB 0:00:06 [ 464MiB/s] [ <=> ]\r" + ], + [ + 1.000019, + "3.09GiB 0:00:07 [ 466MiB/s] [ <=> ]\r" + ], + [ + 1.00003, + "3.55GiB 0:00:08 [ 467MiB/s] [ <=> ]\r" + ], + [ + 1.0, + "3.99GiB 0:00:09 [ 452MiB/s] [ <=> ]\r" + ], + [ + 0.999962, + "4.43GiB 0:00:10 [ 451MiB/s] [ <=> ]\r" + ], + [ + 1.000027, + "4.88GiB 0:00:11 [ 459MiB/s] [ <=> ]\r" + ], + [ + 1.000061, + "5.32GiB 0:00:12 [ 451MiB/s] [ <=> ]\r" + ], + [ + 0.999986, + "5.76GiB 0:00:13 [ 449MiB/s] [ <=> ]\r" + ], + [ + 0.999944, + "6.19GiB 0:00:14 [ 441MiB/s] [ <=> ]\r" + ], + [ + 0.999991, + "6.64GiB 0:00:15 [ 453MiB/s] [ <=> ]\r" + ], + [ + 1.000027, + "7.07GiB 0:00:16 [ 442MiB/s] [ <=> ]\r" + ], + [ + 1.00001, + " 7.5GiB 0:00:17 [ 442MiB/s] [ <=> ]\r" + ], + [ + 1.000009, + "7.93GiB 0:00:18 [ 440MiB/s] [ <=> ]\r" + ], + [ + 0.999988, + "8.37GiB 0:00:19 [ 449MiB/s] [ <=> ]\r" + ], + [ + 1.000024, + "8.81GiB 0:00:20 [ 445MiB/s] [ <=> ]\r" + ], + [ + 0.99992, + "9.26GiB 0:00:21 [ 461MiB/s] [ <=> ]\r" + ], + [ + 1.000016, + "9.71GiB 0:00:22 [ 461MiB/s] [ <=> ]\r" + ], + [ + 0.129892, + "9.77GiB 0:00:22 [ 451MiB/s] [ <=> ]\r\r\n" + ], + [ + 0.000604, + "miguel@megaloman:~/git/haskell/base64$ " + ] + ] +} \ No newline at end of file diff --git a/00_blog/00040_Haskell/00065_Base64-Encoder/index.md b/00_blog/00040_Haskell/00065_Base64-Encoder/index.md new file mode 100644 index 0000000..bdbae41 --- /dev/null +++ b/00_blog/00040_Haskell/00065_Base64-Encoder/index.md @@ -0,0 +1,21 @@ + February 2018 +Miguel's Base64 Encoder +======================= + +Initially coded on a cold winter afternoon to fully understand **base64 encoding** and play with +**Haskell**, which is always an indisputable pleasure. Hacked together in _big anger_, due to my +friend Nick's fairy tales about saving his encrypted binary data in plain _ASCII_ +configuration files,... featuring strange letters and non-printable characters. :smile: + +After optimizing quite a bit, the encoder performs around **460MB/s** on a single core of my _i7-4790K_. + + + +The source code below was auto-fetched from: + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +{BEGIN:EMBED} +https://gitweb.softwarefools.com/?p=miguel/haskell.git;a=blob_plain;f=base64/base64.hs +{END:EMBED} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/00_blog/00040_Haskell/00120_Lambda-Calculus/index.md b/00_blog/00040_Haskell/00120_Lambda-Calculus/index.md new file mode 100644 index 0000000..b86950f --- /dev/null +++ b/00_blog/00040_Haskell/00120_Lambda-Calculus/index.md @@ -0,0 +1,39 @@ + May 2018 +Lambda Calculus +=============== + +Playing with Type Quantifiers and Haskell's Rank 2 Type Polymorphsim, +implementing Boolean logic from scratch. We use the conventional +definitions for `True` an `False` also known as Church booleans, after Alonzo Church, who +intruced them along Lambda Calculus in the 1930s [[1]](#ref). + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +{-# LANGUAGE Rank2Types #-} + +fTrue :: forall a. a->a->a +fTrue x y = x + +fFalse :: forall a. a->a->a +fFalse x y = y + +fAnd :: (forall a. a->a->a)->(forall a. a->a->a)->(forall a. a->a->a) +fAnd p q = p q p + +fOr :: (forall a. a->a->a)->(forall a. a->a->a)->(forall a. a->a->a) +fOr p q = p p q + +fNot :: (forall a. a->a->a)->(forall a. a->a->a) +fNot p = p fFalse fTrue + +ifThenElse :: (forall a. a->a->a)->(forall a. a->a->a) + ->(forall a. a->a->a)->(forall a. a->a->a) +ifThenElse p a b = p a b + +-- Example -- + +main = print $ (ifThenElse fFalse fFalse $ fAnd fTrue $ fNot fFalse) "T" "F" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Ref + +* [1] diff --git a/00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png b/00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png new file mode 100644 index 0000000..19b47f0 Binary files /dev/null and b/00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png differ diff --git a/00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md b/00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md new file mode 100644 index 0000000..cc0aa28 --- /dev/null +++ b/00_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md @@ -0,0 +1,21 @@ + May 2018 +Simple Calculator on Parsec and GTK +=================================== + +![](scale_calc.png){ width=220px } + +Today I implemented this simple stupid calulator as a side effect of playing +around with parsec [1] and haskells gtk3 [2] bindings, as well as glade [3] - +an interactive user interface designer. + +Source Files +------------ + +* + +Ref +--- + +* [1] +* [2] +* [3] diff --git a/00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md b/00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md new file mode 100644 index 0000000..2c21d91 --- /dev/null +++ b/00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md @@ -0,0 +1,27 @@ + May 2018 +A Minimalistic SVG Generator +============================ + + + +A minimalistic SVG generator for my humble requirements. +They might grow someday however... + +The SVG in the following screenshot was generated from the following code +to demonstrate a simple use case. + +The source code below was auto-fetched from: + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +{BEGIN:EMBED} +https://gitweb.softwarefools.com/?p=miguel/haskell.git;a=blob_plain;f=simpleSVG/TestSvg.hs +{END:EMBED} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +![](svg.png){.img-fluid .border} + +Source Files +------------ + +* diff --git a/00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/svg.png b/00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/svg.png new file mode 100644 index 0000000..d679fad Binary files /dev/null and b/00_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/svg.png differ diff --git a/00_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md b/00_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md new file mode 100644 index 0000000..6e4418b --- /dev/null +++ b/00_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md @@ -0,0 +1,175 @@ + March 2019 +# Applicative vs. Monadic Parsing + +Some _real world parsers_ as _Parsec_, let us choose between applicative and +monadic parsing. The applicative style should be sufficient to parse +_context-free_ languages and is easier to reason about, but it is not capable +of parsing _context-sensitive_ grammars. + +## Functor, Applicative, Alternative, Monad + +Before we discuss Applicative and Monadic Parsing, it is important to +understand what Functors, Applicative Functors, Alternatives and Monads +have to offer. When in doubt simply look up the type-class definition. + +Two well-known data types which are instances of all of the above are +**Maybe** and **List**. Try it yourself in _GHCi_. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +-- Maybe as Functor +fmap (+20) (Just 10) +fmap (+20) (Nothing) + +-- List as Functor +fmap (+20) [1..10] + +-- Maybe as Applicative Functor +Nothing <*> Just (22) +Just (+1) <*> Nothing +Just (+15) <*> Just (22) + +-- List as Applicative Functor +[]<*>[1..5] +[(+1),(+15)]<*>[] +[(+1),(+15)]<*>[1..5] + +-- Maybe as Alternative +Nothing <|> Just 5 +Just 5 <|> Nothing +Just 22 <|> Just 10 + +-- List as Alternative +[1..5] <|> [5..10] + +-- Maybe as Monad +Just 5 >>= Just . (+10) +Just 5 >>= return . (+10) +Just 10 >>= return . (+5) >>=return . (+10) +Nothing >>= return . (+5) >>=return . (+10) +Just 10 >>= \x-> return (x*2) >>=return . (+x`div`2) + +-- List as Monad +[1..10] >>= (:[]) . (*5) +[1..5] >>= return . (^2) +[[1..5],[5..10],[],[12]]>>=id +[[1..5],[5..10],[],[12]]>>= map (*4) +[1..5] >>= \a -> [100..100+a] >>= \b -> return (a+b) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Simple Parser + +Our simple toy Parser simply encapsulates a parsing function that returns +_Nothing_ if parsing fails. Otherwise a _pair_ consisting of the parsed and +unparsed input inside its respective elements. + +Notice that we made our Parser instance of all the type-classes already. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +data Parser a b = Parser (a->Maybe (b,a)) + +instance Functor (Parser a) where + fmap f p = Parser g + where g inp = case parse p inp of Just (x,y) -> Just (f x,y) + _ -> Nothing + +instance Applicative (Parser a) where + pure v = Parser (\inp -> Just (v,inp)) + pg <*> px = Parser g + where g inp = case parse pg inp of Just (f,b) -> parse (fmap f px) b + _ -> Nothing + +instance Alternative (Parser a) where + empty = Parser (\_ -> Nothing) + p1 <|> p2 = Parser g + where g inp = case parse p1 inp of Nothing -> parse p2 inp + x -> x + +instance Monad (Parser a) where + return = pure + p >>= f = Parser g + where g inp = case parse p inp of Just (a,b) -> parse (f a) b + _ -> Nothing + +parse :: Parser a b -> a -> Maybe (b,a) +parse (Parser f) inp = f inp +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Primitives + +We also need at least a minimal set of primitives to parse something. +Note that the primitives can give you the effects of Applicative or +Alternative even if there's no instance (as dmwit pointed out on #haskell). +E.g. the _word_ primitive below, could not be composed, by combining the +_char_ parsers in an applicative style only. + +The _num_ parser makes use of the _some_ combinator which requires our +Parser to be an instance of _Alternative_ as well. _Applicative_ +alone is of limited use in practice since without it, we also lack +the <|> combinator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +word :: String -> Parser String String +word w = Parser g where l = length w + g inp = if take l inp == w then Just (w,drop l inp) + else Nothing + +satisfy :: (Char -> Bool) -> Parser String Char +satisfy f = Parser g where g (x:xs) | f x = Just (x,xs) + g _ = Nothing + +space :: Parser String Char +space = satisfy (==' ') + +char :: Char -> Parser String Char +char c = satisfy (==c) + +notChar :: Char -> Parser String Char +notChar c = satisfy (/=c) + +num :: Parser String Int +num = read <$> some (satisfy isDigit) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Applicative / Alternative parsing + +Let's parse something! + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +-- well-formed parentheses are the canonical example of a context-free grammar +parsePar = concat <$> some parseP where parseP = word "()" <|> (char '(' *> parsePar <* char ')') +parse parsePar "((()())()())" + +-- a simple context-free language with matching pairs of a's and b's, which is not regular +parseAB = (\a x b -> a:x++"b") <$> char 'a' <*> parseAB <*> char 'b' <|> word "ab" +parse parseAB "aaaaabbbbb" + +-- parse basic mathematical operations and calulate the results. +parseOp op sig = (pure (op) <* many space <*> num <* many space <* char sig <* many space <*> num ) +parse (parseOp (+) '+' <|> parseOp (-) '-' <|> parseOp (*) '*' <|> parseOp (div) '/') " 111 * 747 " +parse (parseOp (+) '+' <|> parseOp (-) '-' <|> parseOp (*) '*' <|> parseOp (div) '/') "111+747" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Monadic parsing of context-sensitive grammars + +The canonical non-context-free language can not be caputred by applicative parsing anymore: $$\{a^n b^n c^n : n \geqslant 1\}$$ + +The following monadic parser will work here: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +parseABC = length <$> (many $ char 'a') >>= \la -> + length <$> (many $ char 'b') >>= \lb -> + length <$> (many $ char 'c') >>= \lc -> + if la==lb&&lb==lc then pure ("ABCok") else empty + +parse parseABC "aaaaabbbbbccccc" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Summary + +As usual, use the simplest tool that will suffice :smile: + +## Ref / Further Reading + +* +* +* diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md new file mode 100644 index 0000000..5060081 --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md @@ -0,0 +1,20 @@ +# Pandoc Color Themes + +Color-themes for syntax-highlighting obtained from Pandoc. +E.g. To get the pygments theme you need to have some source-code embedded +in your markdown and run: + + stack exec pandoc -- -s file.md --highlight-style pygments + +Then you can extract the css from the resulting standalone html file. +Here you can find my extracted html files for reference: + +* [breezedark](index_breezedark.html) +* [espresso](index_espresso.html) +* [haddock](index_haddock.html) +* [kate](index_kate.html) +* [monochrome](index_monochrome.html) +* [pygments](index_pygments.html) +* [tango](index_tango.html) +* [zenburn](index_zenburn.html) + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html new file mode 100644 index 0000000..6b89b97 --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html @@ -0,0 +1,117 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html new file mode 100644 index 0000000..6b0d627 --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html @@ -0,0 +1,113 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html new file mode 100644 index 0000000..5c5af29 --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html @@ -0,0 +1,109 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html new file mode 100644 index 0000000..03aa0c6 --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html @@ -0,0 +1,117 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html new file mode 100644 index 0000000..60c229d --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html @@ -0,0 +1,96 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html new file mode 100644 index 0000000..e637f29 --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html @@ -0,0 +1,114 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html new file mode 100644 index 0000000..f76564b --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html @@ -0,0 +1,113 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html new file mode 100644 index 0000000..f186f69 --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html @@ -0,0 +1,113 @@ + + + + + + + index + + + + + + + + diff --git a/00_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md new file mode 100644 index 0000000..a66c99c --- /dev/null +++ b/00_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md @@ -0,0 +1,63 @@ + April 2018 +# estático - static website generator + +A few weeks ago I decided to switch my website from a well known PHP +driven CMS solution, to a light and static set of HTML pages. + +And so I wrote ... a simple static website generator in **Haskell**. +Of course I know that there are plenty of these out there, still I wanted +my very own masturbatory solution. + +I use **pandoc** et al. for most of the work anyway. + +## Features + +* **No** Database +* Generate HTML from **Markdown** with **pandoc** +* **Highlight** source-code with **pandoc** +* Embed data **fetched** from the web with **http-conduit** +* Embed **screen-casts** with **asciinema** +* Embed Latex formulas with **MathJx** +* Scale Images with **ImageMagick** +* Generate MP4 from OGG **Videos** with **ffmpeg** + +## Try It +You can find the most recent version following the links below. +Build it with _stack_ or use the docker images. + +* +* +* + +## Pandoc Themes + +Here I put together the themes available for syntax-highlighting, extracted +from **pandoc**: [./pandoc\_colors](./pandoc_colors) + +## Example Website + +This very website is a real-world example making +use of estático. You can find it's sources here: + +* + +## Example Usage (Docker) + +__NOTE: make sure DIR\_OUT exists and is a free directory__ + +You can use the example websites inside the examples/ directory for a start. + +Inside the input directory (e.g. ./examples/example01/) run something along this lines: + + DIR_IN=`pwd` + DIR_OUT=/mnt/yourwebsiteroot + HTML_ROOT=https://www.example.com + SUDO=sudo + IMAGE=migueldirty/estatico + ${SUDO} docker run --rm -v${DIR_IN}:/in:ro -v${DIR_OUT}:/out:rw ${IMAGE} /in /out ${HTML_ROOT} + +Or if you want to test it locally use some local DIR\_OUT and HTML\_ROOT instead: + + DIR_OUT=/home/miguel/testpage + HTML_ROOT=/home/miguel/testpage + diff --git a/00_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md b/00_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md new file mode 100644 index 0000000..f9b3a4e --- /dev/null +++ b/00_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md @@ -0,0 +1 @@ +Coming sooner... or later. diff --git a/00_blog/00040_Haskell/index.md b/00_blog/00040_Haskell/index.md new file mode 100644 index 0000000..2c02a65 --- /dev/null +++ b/00_blog/00040_Haskell/index.md @@ -0,0 +1,8 @@ +Haskell +======= + +Originally coming from structured and object-oriented programming, I fell +in love with Haskell a couple of years ago. I appreciate it's purity +and laziness and the powerful, static type system. + +You can find here my notes and tiny toy projects related to Haskell. -- cgit v1.2.3