Cardinality-0.2: examples/HelloWorld.hs
{-
Copyright (C) 2010 Andrejs Sisojevs <andrejs.sisojevs@nextmail.ru>
All rights reserved.
For license and copyright information, see the file COPYRIGHT
-}
--------------------------------------------------------------------------
--------------------------------------------------------------------------
{-# LANGUAGE MultiParamTypeClasses #-}
import Data.Cardinality
import Data.List
import System.IO
data MyContainer a =
MyContainer {
field_1 :: Maybe a
, field_2 :: (a, a, a)
, field_3 :: a
, field_4 :: [a]
}
deriving (Show)
emptiestMyContainer :: MyContainer Int
emptiestMyContainer = MyContainer Nothing (1,1,1) 1 []
instance HasCard (MyContainer a) where
cardOf mc = sumLCs
[ cardOf $ field_1 mc -- 0..1
, cardOf $ field_2 mc -- 3 (uses instance HasCard (a,a,a))
, preciseC 1
, cardOf $ field_4 mc -- 0..Inf
] -- = 4..Inf
instance HasCardT MyContainer where
cardOfT = cardOf
instance HasCardConstr (MyContainer a) where
cardinalityConstraintOf mc_a = cardinalityRange (cardOf emptiestMyContainer) infiniteC
instance HasCardConstrT MyContainer where
cardinalityConstraintOfT = cardinalityConstraintOf
instance HasCardUCT (MyContainer a) [a] where
uContTrans mc_a =
uContTrans (field_1 mc_a)
++ uContTrans (field_2 mc_a)
++ [field_3 mc_a]
++ field_4 mc_a
instance HasCardUCT_T MyContainer [] where
uContTransT = uContTrans
-- We will use this function to instaniate both @HasCardUCT@ and @HasCardUCT_T@.
-- They must use different error throwers, that's why had to define transform
-- outside of instances - in order to avoid doublecoding the same thing.
__uContTrans :: (TransformError_Details -> MyContainer a) -> [a] -> MyContainer a
__uContTrans error_fun a_list = result
where
result =
case a_list of
(e1 : e2 : e3 : e4 : rest_a_list_1) ->
case rest_a_list_1 of
(e5 : rest_a_list_2) ->
MyContainer {
field_1 = Just e1
, field_2 = (e2,e3,e4)
, field_3 = e5
, field_4 = rest_a_list_2
}
_ -> MyContainer {
field_1 = Nothing
, field_2 = (e1,e2,e3)
, field_3 = e4
, field_4 = rest_a_list_1
}
_ -> error_fun "not enough elements in list"
instance HasCardUCT [a] (MyContainer a) where
uContTrans = __uContTrans (uContError "[a]" "MyContainer a")
instance HasCardUCT_T [] MyContainer where
uContTransT = __uContTrans (uContErrorT "[]" "MyContainer")
main = do
let f pr c = pr ++ (concat $ intersperse "\n" $ map show c)
let output1 = f "Initial MyContainers:\n" initial_containers
let output2 = f "MyContainers trasformed to lists:\n" initial_containers2lists
let output3 = f "Initial lists:\n" initial_lists
let output4 = f "Lists trasformed to MyContainers:\n" initial_lists2containers
putStrLn output1
pressAnyKey
putStrLn output2
pressAnyKey
putStrLn output3
pressAnyKey
putStrLn output4
pressAnyKey
where
initial_containers :: [MyContainer Int]
initial_lists :: [[Int]]
initial_containers2lists :: [Maybe [Int]]
initial_lists2containers :: [Maybe (MyContainer Int)]
---------------------------------
initial_containers =
[ MyContainer (Just 1) (2,3,4) 5 [6,7,8,9,10]
, MyContainer (Just 1) (2,3,4) 5 []
, MyContainer Nothing (2,3,4) 5 [6,7,8,9,10]
, MyContainer Nothing (2,3,4) 5 []
]
initial_lists =
[ []
, [1]
, [1..3]
, [1..4]
, [1..10]
, [1..5]
, [2..10]
]
initial_containers2lists = map sContTrans initial_containers
initial_lists2containers = map sContTrans initial_lists
---------------------------------------------------------------
-- helpers
infixr 1 <<
(<<) :: Monad m => m b -> m a -> m b
f << x = x >> f
putStrLn_paged :: Int -> String -> IO ()
putStrLn_paged page_size s = f $ lines s
where
f lines_list =
let (to_print, to_next_itera) = splitAt page_size lines_list
in do putStrLn (concat $ intersperse "\n" to_print)
case null to_next_itera of
True -> return ()
False -> f to_next_itera << pressAnyKey
pressAnyKey = hGetChar stdin << putStrLn "\n-------Press any key to continue...-------"