Skip to content

Instantly share code, notes, and snippets.

@davidallsopp
davidallsopp / ZipLines.hs
Last active August 29, 2015 14:09
Listing all lines from all entries in a ZIP archive, using the zip-conduit package in Haskell
module ZipLines where
-- requires zip-conduit package
-- See examples in docs at:
-- https://hackage.haskell.org/package/zip-conduit-0.2.2.1/docs/Codec-Archive-Zip.html
-- and (rather more useful) example at:
-- http://stackoverflow.com/a/20153522/699224
import Control.Monad.IO.Class (liftIO) -- requires "transformers" package. What about mtl?
import Data.Conduit
@davidallsopp
davidallsopp / Taps.scala
Created November 27, 2014 12:06
Utilities to enable side-effects (logging, updating mutable counters etc) in the middle of a functional (map/flatmap/filter etc) chain of calls.
/**
* Enrich any object so we can run side-effects (such as logging) without needing temporary variables.
*
* <p>Adapted from http://naildrivin5.com/blog/2012/06/22/tap-versus-intermediate-variables.html
*
* <pre>
* "foobar".tap { s => if (s.contains("bar")) println("Got bar") }.toUpperCase()
* </pre>
*/
implicit class Tap[A](obj: A) {
@davidallsopp
davidallsopp / diamond4.md
Last active August 29, 2015 14:10
Diamond kata using symmetry and a Scala Worksheet

This is one of my attempts (the 4th) at the diamond kata, in Scala (See Ron Jeffries' article: http://ronjeffries.com/articles/diamond3/three-of-diamonds.html). This version makes explicit use of the symmetry of the diamond by generating one quadrant of it, then reflecting that quadrant twice to generate the entire diamond.

UPDATE: I have added my 2nd and 3rd (and now 5th, and 6th in Haskell) solutions for comparison at the bottom of the page. The 1st solution is somewhere out of reach at the time of writing! The serious business of TDD degenerates into a bit of an obfuscated one-liner contest at this point ;-)

UPDATE: see also Ron Jeffries' article (http://ronjeffries.com/articles/diamond/diamond.html) which also uses the symmetry - I didn't read this one until afterwards.

I wrote it as an Eclipse Scala worksheet. These worksheets evaluate and display the results of each expression whenever an edit is made, rather like a persistent REPL. This provides great visibility and feedback on your code, so I find

@davidallsopp
davidallsopp / Forever.hs
Last active August 29, 2015 14:14
Looping forever with a recursive main. Haskell IO is often explained in terms of main returning an IO value then being executed by the runtime, but it's less clear what goes on when main apparently never terminates. See https://stackoverflow.com/questions/28203214/why-how-does-recursive-io-work
module Forever where
main :: IO ()
main = do
line <- getLine
putStrLn line
main
-- or if you prefer point-free style:
module Conduit1 where
-- From conduit author's tutorial at
-- https://www.fpcomplete.com/school/to-infinity-and-beyond/pick-of-the-week/conduit-overview
-- via https://www.fpcomplete.com/user/jwiegley/conduit-tour
-- needs packages: conduit
import Data.Conduit
-- core data types and primitive operations.
{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
-- Use overloaded strings so we can mix and match Text and string literals
-- Use DeriveGeneric so we can create our toJSON and FromJSON instances automatically
module Aeson.Intro where
import Data.Aeson
import Data.Text
import Data.Monoid
import qualified Data.ByteString.Lazy as Lazy
@davidallsopp
davidallsopp / MonadicIO.hs
Last active August 29, 2015 14:14
Starting from the assumption of pure IO, showing that the signature of bind (>>=) arises naturally as a consequence of chaining IO values together.
module MonadicIO where
-- For pure FP, functions must be pure
-- So IO-related functions must return a value rather than having a side-effect
-- e.g. reading a line: getLine gives us an IO String (an IO that, when executed, would produce a String)
myGetLine :: IO String
myGetLine = getLine
-- e.g. writing a line: putStrLn accepts a String, and produces an IO () that, when executed, has an effect
@davidallsopp
davidallsopp / roman.hs
Last active February 8, 2017 14:26
Haskell version of the Roman numeral converter, using unfold. Taken from https://www.reddit.com/r/programming/comments/658ys/how_to_recognise_a_good_programmer/c02vm1j. There is a code walkthrough at http://billmill.org/roman.html. See also Scala version at https://gist.github.com/davidallsopp/6711935 and reverse program (roman numeral parser) i…
import Data.List (find, unfoldr)
import Control.Arrow (second)
import Control.Applicative ((<$>)) -- for second version
numerals :: [(String, Int)]
numerals = [("M",1000),("CM",900),("D",500),("CD",400),("C",100),("XC",90),
("L",50),("XL",40),("X",10),("IX",9),("V",5),("IV",4),("I",1)]
romanize :: Int -> String
romanize = concat . unfoldr next
import Data.List (isPrefixOf)
numerals = [("M",1000),("CM",900),("D",500),("CD",400),("C",100),("XC",90),
("L",50),("XL",40),("X",10),("IX",9),("V",5),("IV",4),("I",1)]
toArabic :: String -> Int
toArabic "" = 0
toArabic str = num + toArabic xs
where (num, xs):_ = [ (num, drop (length n) str) | (n,num) <- numerals, isPrefixOf n str ]
@davidallsopp
davidallsopp / repeat.js
Last active August 29, 2015 14:16
Repeating a function using setTimeout rather than setInterval
// Poll repeatedly. Use setTimeout rather than setInterval
// to ensure previous execution has completed before enqueing a new one
(function repeat() {
do_something();
setTimeout(repeat, 2000);
})();
// The repeat function's scope is limited, so one can have multiple blocks like this
// without them interfering - and can wrap this in a helper function in the style of