diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 1996-2010 Addison-Wesley
+Copyright (c) 2012 Roman Cheplyaka
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Pictures.hs b/Pictures.hs
new file mode 100644
--- /dev/null
+++ b/Pictures.hs
@@ -0,0 +1,143 @@
+module Pictures
+  ( Picture
+  , horse
+  , flipV
+  , flipH
+  , above
+  , beside
+  , superimpose
+  , invertColour
+  , scale
+  , black
+  , white
+  )
+  where
+
+import Test.SmallCheck
+import Test.SmallCheck.Series
+import Data.List
+import Control.Monad
+
+newtype Picture = Picture [[Char]]
+  deriving Eq
+
+-- The example used in Craft2e: a polygon which looks like a horse. Here
+-- taken to be a 16 by 12 rectangle.
+
+horse :: Picture
+
+horse = Picture
+        ["       ##   ",
+         "     ##  #  ",
+         "   ##     # ",
+         "  #       # ",
+         "  #   #   # ",
+         "  #   ### # ",
+         " #    #  ## ",
+         "  #   #     ",
+         "   #   #    ",
+         "    #  #    ",
+         "     # #    ",
+         "      ##    "]
+
+-- Completely white and black pictures.
+
+white :: Picture
+
+white = Picture [" "]
+
+black = Picture ["#"]
+
+-- Getting a picture onto the screen.
+
+instance Show Picture where
+  show (Picture p) = "\n" ++ concatMap (\x -> "|" ++ x ++ "|\n") p
+
+-- SmallCheck generator
+instance Serial Picture where
+  series d = do
+    size <- [0..d]
+    map (fromList size) $ replicateM (size^2) [' ', '#']
+
+  coseries = error "Picture.coseries"
+
+fromList :: Int -> [Char] -> Picture
+fromList size cs = Picture $ unfoldr f cs
+  where
+  f [] = Nothing
+  f xs = Just $ splitAt size xs
+
+-- Transformations of pictures.
+
+pic :: ([[Char]] -> [[Char]]) -> Picture -> Picture
+pic f (Picture p) = Picture $ f p
+
+pic2 :: ([[Char]] -> [[Char]] -> [[Char]]) -> Picture -> Picture -> Picture
+pic2 f (Picture p1) (Picture p2) = Picture $ f p1 p2
+
+-- Reflection in a vertical mirror.
+
+flipV :: Picture -> Picture
+
+flipV = pic $ map reverse
+
+-- Reflection in a horizontal mirror.
+
+flipH :: Picture -> Picture
+
+flipH = pic reverse
+
+-- Rotation through 180 degrees, by composing vertical and horizontal
+-- reflection. Note that it can also be done by flipV.flipH, and that we
+-- can prove equality of the two functions.
+
+rotate :: Picture -> Picture
+
+rotate = flipH . flipV
+
+-- One picture above another. To maintain the rectangular property,
+-- the pictures need to have the same width.
+
+above :: Picture -> Picture -> Picture
+
+above = pic2 (++)
+
+-- One picture next to another. To maintain the rectangular property,
+-- the pictures need to have the same height.
+
+beside :: Picture -> Picture -> Picture
+
+beside = pic2 $ zipWith (++)
+
+-- Superimose one picture above another. Assume the pictures to be the same
+-- size. The individual characters are combined using the combine function.
+
+superimpose :: Picture -> Picture -> Picture
+
+superimpose = pic2 $ zipWith (zipWith combine)
+
+-- For the result to be '.' both components have to the '.'; otherwise
+-- get the '#' character.
+
+combine :: Char -> Char -> Char
+
+combine topCh bottomCh
+  = if (topCh == ' ' && bottomCh == ' ')
+    then ' '
+    else '#'
+
+-- Inverting the colours in a picture; done pointwise by invert...
+
+invertColour :: Picture -> Picture
+
+invertColour = pic $ map (map invert)
+
+-- ... which works by making the result '.' unless the input is '.'.
+
+invert :: Char -> Char
+
+invert ch = if ch == ' ' then '#' else ' '
+
+scale :: Int -> Picture -> Picture
+scale n = pic $ \ls ->
+  map (>>= replicate n) ls >>= replicate n
diff --git a/README.txt b/README.txt
new file mode 100644
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,3 @@
+Code for the Haskell course taught at the Odessa National University in 2012.
+
+Based on http://hackage.haskell.org/package/Craft3e
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/onu-course.cabal b/onu-course.cabal
new file mode 100644
--- /dev/null
+++ b/onu-course.cabal
@@ -0,0 +1,25 @@
+-- Initial onu-course.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                onu-course
+version:             1
+synopsis:            Code for the Haskell course taught at the Odessa National University in 2012
+description:         Based on <http://hackage.haskell.org/package/Craft3e>
+license:             MIT
+license-file:        LICENSE
+author:              Roman Cheplyaka
+maintainer:          Roman Cheplyaka <roma@ro-che.info>
+copyright:           Addison Wesley; Roman Cheplyaka
+category:            Education
+build-type:          Simple
+cabal-version:       >=1.8
+extra-source-files:  README.txt
+
+Source-repository head
+  type:     git
+  location: git://github.com/feuerbach/onu-course.git
+
+library
+  exposed-modules:     Pictures
+  -- other-modules:       
+  build-depends:       base >= 4 && < 5, smallcheck >= 0.6
