Just looked at Lenses in Haskell Holy crap!

theworstmathematician:

i found it

uncurry . flip . const . (uncurry $ flip $ const $ (==))

Alternative?

-- on from Data.Function
on (==) fst

(Source: twocubes)

4 notes

Haskell, Sum to Zero

Problem description: Sum to Zero

You are given an array of integers. Count the numbers of ways in which the sum of 4 elements in this array results in zero.

Descriptive Haskell solution:

--  Cons a value onto the beginning
--  of every element in a list
(•) = map . (:)

--  Find the combinations of a list
combs = foldr (\y vs -> vs ++ (y • vs)) [[]]

--  Given a number k and a list vs
--  The length of vs must equal k
--  And the sum of vs must equal 0
predicate k vs = (length vs == k) && (sum vs == 0)

--  Find the combinations of a list
--  Filtered by the predicate
filtered_combs k = filter (predicate k) . combs

--  Count the number of filtered combinations
process k = length . filtered_combs k

MONOLITHIC Haskell version

cthulhu k
  = length
  . filter (\xs -> length xs == k && sum xs == 0)
  . foldr (\y vs -> vs ++ (map (y:) vs)) [[]]

I’m aware that there is likely a more efficient way of computing this – in which only those combinations that are of the correct length are computed – maybe I’ll work on that next…

Functional Thinking with Neal Ford

Execution in the Kingdom of Nouns

Great post about Java, OOP, and Functional Programming.

Clojure Slurry

Been playing with Haskell for a while, I’m now going back to Clojure :].

Came up with a function called slurry. It’s pretty much currying with splat application (use of variadic arguments).

A simple example:

; slurried map of 2 arguments
(def smap2 (slurry map 2))

; can use as normal map
(smap2 inc [1 2 3 4]) ;=> (2 3 4 5)

; can use curried
(def inc-map (smap2 inc))
(inc-map [1 2 3 4]) ;=> (2 3 4 5)

For convienience I’ve created two macros to help with the creation of slurried functions. These include slurryfn and defslurry.

slurryfn allows the curry arity to be calculated from the argument list. defslurry is a shortcut for using def with a slurryfn value. Examples follow:

; Using defslurry
(defslurry f [a b c]
  (+ a (* b c)))

; Equivalent using slurryfn
(def f
  (slurryfn [a b c]
    (+ a (* b c))))

; Equivalent using slurry
(def f
  (slurry
    (fn [a b c]
      (+ a (* b c)))
    3))
; note the explicit arity count: 3

The following is my implementation of the three functions/macros:

(defn slurry
  ([f] (slurry f 0 []))
  ([f n] (slurry f n []))
  ([f n _args]
    (fn [& n_args]
      (let [args (concat _args n_args)]
          (if (< (count args) n)
            (slurry f n args)
            (apply f args))))))

(defmacro slurryfn [args & tail]
  `(slurry
    (fn ~args ~@tail)
    ~(count args)))

(defmacro defslurry [name & tail]
  `(def ~name
    (slurryfn ~@tail)))

Resources:

Monads

I now understand Haskell’s Monads; this guide helped. Booyahh.

Just came up with two similar mapping functions in Clojure: map-grid and map-tree.

map-grid

Given a regular n-dimensional table of data, apply a function to each cell along with its index path specific to a given depth. For example, with the following 2 dimensional table:

(def table
  [ [0 1 0]
    [0 1 0]
    [0 1 0] ])

To generate a hash-map from locations to data, one might write:

;;  For rows as data:
(apply merge (flatten (map-grid 1 hash-map table)))

;;  Resulting in:
;;  {[1] [0 1 0],
;;   [2] [0 1 0],
;;   [0] [0 1 0]}


;;  For cells as data
(apply merge (flatten (map-grid 2 hash-map table)))

;;  Resulting in:
;;  {[2 1] 1,
;;   [1 0] 0,
;;   [2 2] 0,
;;   [0 0] 0,
;;   [1 1] 1,
;;   [0 1] 1,
;;   [1 2] 0,
;;   [0 2] 0,
;;   [2 0] 0}

map-grid accepts a depth-level a function and some data. The depth-level specifies how deep to traverse the data. The function describes the transformation of a cell with access to the cells index path.

The definition of map-grid is as follows:

(defn map-grid
  ([depth f data] (map-grid depth f data []))
  ([depth f data levels]
    (if (zero? depth)
      (f levels data)
      (map-indexed
        (fn [i v]
          (map-grid (dec depth) f v (conj levels i)))
        data))))

map-tree

This function doesn’t allow for the depth to be specified - if a collection is found, it will iterate through it. Defined as follows:

(defn map-tree
  ([f data] (map-tree f data []))
  ([f data levels]
    (if (coll? data)
      (map-indexed
        (fn [i v]
          (map-tree f v (conj levels i)))
        data)
      (f levels data))))

Clojure TypeMatch

I started a new Clojure project today: a module allowing complex type matching. More information is available on its GitHub page: github.com/LiamGoodacre/TypeMatch

Haskell: Project Euler - Problem 1 Extension

My solution to problem 1 was a function that accepted two multiplier values and a limit. I decided to write an extension that allowed a list of multiplier values. The following is the result (and is still pretty short!):

--  Function Solution
euler1x l = sum . foldl (\x y->union x [y,y+y..l-1]) []

--  Example:
euler1x 1000 [3,5]

Yay Haskell!

Haskell: Project Euler - Problem 2

Problem 2: By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

--  Original approach
euler2 m = let fib x y = x:fib y (x+y) in
  sum $ takeWhile (< m) $ filter even $ fib 1 1

--  Secondary approach (not generating odd values)
euler2b m = let gen x y = (x+y):gen (x + 2*y) (2*x + 3*y) in
  sum $ takeWhile (< m) $ gen 1 1
0 notes

Haskell: Project Euler - Problem 1

I’ve decided to go through Project Euler in an attempt to learn Haskell. (Yay Haskell*)

I’m also setting out to attempt interesting, short, or efficient approaches to the problems - depending on my mood and interest.


Problem: Add all the natural numbers below one thousand that are multiples of 3 or 5.

--  Include the union function
import Data.List (union)

--  Function for computation
euler1 a b l = sum $ union [a,a+a..l-1] [b,b+b..l-1]

--  Application example
euler1 3 5 1000
--  result => 233168

*Yay Haskell!

Monads: just casually blowing my mind! Revision can be delayed until tomorrow.

2 notes