Dockerimage für GHC7.8 und GHC7.6

Ich habe heute ein Dockerfile für GHC7.8 bzw. GHC7.6 mit Cabal 1.20.0.1 auf Ubuntu 14.04 (LTS) geschrieben. Die Dockerfiles selbst liegen auf Github und die Images werden per „trusted builds“ automatisch ins Docker Index hochgeladen (GHC7.8, GHC7.6).

Aufbauend auf diesem Image kann man nun zum Beispiel Dockerfiles für seine eigenen Haskell-Projekte schreiben. Ich zeige das kurz an einem Beispiel, dem funblog.

FROM agrafix/ghc7.6
MAINTAINER mail@agrafix.net
RUN git clone https://github.com/agrafix/funblog.git
RUN cd funblog && cabal install --only-dependencies
RUN cd funblog && cabal build
RUN rm -rf /funblog/blog.cfg
ADD blogConfiguration.cfg /funblog/blog.cfg

EXPOSE 8080
CMD ["/funblog/dist/build/funblog/funblog"]

Das Image kann man dann mit

docker build -t 'agrafix/funblog' .

bauen, wobei man eine Datei blogConfiguration.cfg im gleichen Verzeichnis benötigt. (Vorlage dafür ist auf github) Danach kann man den Blog mit

docker run -p 8080:8080 -d agrafix/funblog

starten und unter

http://localhost:8080

aufrufen.

 

GHC 7.6.3 auf Ubuntu 12.04 installieren

Eine Kurzanleitung für’s installieren von GHC-7.6.3, cabal und darcs auf Ubuntu 12.04 (64-Bit):

Zunächst der GHC:

sudo apt-get install gcc libgmp3-dev curl
curl -O http://www.haskell.org/ghc/dist/7.6.3/ghc-7.6.3-x86_64-unknown-linux.tar.bz2
tar -xjvf ghc-7.6.3-x86_64-unknown-linux.tar.bz2 
cd ghc-7.6.3
./configure
make install

Dann cabal:

sudo apt-get install zlib1g-dev 
curl -O http://hackage.haskell.org/packages/archive/cabal-install/1.16.0/cabal-install-1.16.0.tar.gz
tar -xzvf cabal-install-1.16.0.tar.gz
cd cabal-install-1.16.0
sh bootstrap.sh

Dann in der .cabal/config die Zeile „jobs“ auskommentieren.

cabal update
cabal install cabal-install

Dann noch darcs:

sudo apt-get install ncurses-dev libcurl4-gnutls-dev
cabal install darcs
 

Delta Debugging Minimierung mit Haskell

Hier eine Implementierung eines Minimierungsalgorythmus für Delta Debugging in Haskell:

splitInto :: Int -> [a] -> [[a]]
splitInto num lst =
    recSplit [] lst
    where
      recSplit xs part
          | length part  ([a] -> IO Bool) -> [a] -> Int -> IO [a]
ddmin testfun cx n
    | length cx == 1 = return $ cx
    | n < (length cx) = ddmin testfun cx (min (2*n) (length cx))
    | otherwise =
        checkChunk chunks
    where
      checkChunk [] = return $ cx
      checkChunk (x:xs) =
          do res <- testfun (cx \ x)
             if res
             then checkChunk xs
             else ddmin testfun (cx \ x) (max (n-1) 2)

      chunks = splitInto n cx
 

RC4 Haskell und JavaScript

RC4 in JavaScript: (Quelle)

/*
 * RC4 symmetric cipher encryption/decryption
 *
 * @license Public Domain
 * @param string key - secret key for encryption/decryption
 * @param string str - string to be encrypted/decrypted
 * @return string
 */
function rc4(key, str) {
	var s = [], j = 0, x, res = '';
	for (var i = 0; i < 256; i++) {
		s[i] = i;
	}
	for (i = 0; i < 256; i++) {
		j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
		x = s[i];
		s[i] = s[j];
		s[j] = x;
	}
	i = 0;
	j = 0;
	for (var y = 0; y < str.length; y++) {
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		x = s[i];
		s[i] = s[j];
		s[j] = x;
		res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
	}
	return res;
}

RC4 in Haskell:

module RC4
(
 encode,
 decode
)
where

import Data.Map (Map, (!))
import qualified Data.Map as Map
import Data.Char (ord, chr)
import Data.Bits (xor)

encode :: String -> String -> String
encode = rc4

decode :: String -> String -> String
decode = rc4

initS = Map.fromList $ zip [0 .. 255] [0 .. 255]

rc4 :: String -> String -> String
rc4 key str =
    resultStr
    where
      (_, s) = foldl mkBox (0, initS) [0 .. 255]
      mkBox (inpJ, inpS) i =
          (j, s'')
          where
            j = (inpJ + (inpS ! i) + (ord (key !! (i `mod` (length key))))) `mod` 256
            x = inpS ! i
            s' = Map.insert i (inpS ! j) inpS
            s'' = Map.insert j x s'

      (resultStr, _, _, _) = result

      result = foldl core ("", 0, 0, s) [0 .. ((length str) - 1)]
      core (res, inpI, inpJ, inpS) y =
          (res', i, j, s'')
          where
            i = (inpI + 1) `mod` 256
            j = (inpJ + (inpS ! i)) `mod` 256
            x = inpS ! i
            s' =  Map.insert i (inpS ! j) inpS
            s'' = Map.insert j x s'
            k = ((s'' ! i) + (s'' ! j)) `mod` 256
            res' = res ++ [chr $ (ord (str !! y)) `xor` (s'' ! k)]
 

GHC 7.6 auf Mac OSX Lion installieren

Heute musste ich mal wieder GHC 7.6 und cabal-install auf eine Mac installieren. Ich möchte hier nur kurz meine Vorgehensweise dokumentieren:

GHC installieren

Folgende Befehle laden und installieren GHC:

curl -O http://www.haskell.org/ghc/dist/7.6.1/ghc-7.6.1-x86_64-apple-darwin.tar.bz2
tar -xjvf ghc-7.6.1-x86_64-apple-darwin.tar.bz2
cd ghc-7.6.1
./configure
make install

Hinweis: Möchte man ein eigenes Ziel-Directory für die GHC-Binaries wählen, geht das per ./configure --prefix=(hier der pfad)

cabal-install installieren

Folgende Befehle laden und installieren cabal-install (1.16.0)

curl -O http://hackage.haskell.org/packages/archive/cabal-install/1.16.0/cabal-install-1.16.0.tar.gz
tar -xzvf cabal-install-1.16.0.tar.gz
cd cabal-install-1.16.0
sh bootstrap.sh
 

Haskell: Multiplikatives Inverse in einem Restklassenring

Das multiplikative Inverse einer Restklasse in einem Restklassenring kann man in Haskell mit folgendem Snippet berrechnen:

-- multiplicative inverse for a in Z  bZ
mulInverse :: (Int, Int) -> Int
mulInverse (a, m) =
  (x + m) `mod` m
  where
    (gcd, (x, y)) = euclid a m

-- returns (gcd(a,b), (x, y)) in eq ax + by = gcd(a,b)
euclid :: Int -> Int -> (Int, (Int, Int))
euclid 0 b = (b, (0, 1))
euclid a b = 
  (gcd, (y - (x*(b `div` a)), x))
  where
    (gcd, (x, y)) = euclid (b `mod` a) a

Beispiel: Das multiplikative Inverse für 8 im Restklassenring Z / 21 Z ist 8.

$ ghci mulInverse.hs
*Main> mulInverse (8, 21)
8