Files
haskell/exercises/Set5a.hs
T
2020-05-22 17:27:06 +03:00

261 lines
7.4 KiB
Haskell

-- Exercise set 5a
--
-- * defining algebraic datatypes
-- * recursive datatypes
module Set5a where
import Mooc.Todo
------------------------------------------------------------------------------
-- Ex 1: Define the type Vehicle that has four constructors: Bike,
-- Bus, Tram and Train.
--
-- The constructors don't need any fields.
------------------------------------------------------------------------------
-- Ex 2: Define the type BusTicket that can represent values like these:
-- - SingleTicket
-- - MonthlyTicket "January"
-- - MonthlyTicket "December"
------------------------------------------------------------------------------
-- Ex 3: Here's the definition for a datatype ShoppingEntry that
-- represents an entry in a shopping basket. It has an item name (a
-- String), an item price (a Double) and a count (an Int). You'll also
-- find two examples of ShoppingEntry values.
--
-- Implement the functions totalPrice and buyOneMore below.
data ShoppingEntry = MkShoppingEntry String Double Int
deriving Show
threeApples :: ShoppingEntry
threeApples = MkShoppingEntry "Apple" 0.5 3
twoBananas :: ShoppingEntry
twoBananas = MkShoppingEntry "Banana" 1.1 2
-- totalPrice should return the total price for an entry
--
-- Hint: you'll probably need fromIntegral to convert the Int into a
-- Double
--
-- Examples:
-- totalPrice threeApplies ==> 1.5
-- totalPrice twoBananas ==> 2.2
totalPrice :: ShoppingEntry -> Double
totalPrice = todo
-- buyOneMore should increment the count in an entry buy one
--
-- Example:
-- buyOneMore twoBananas ==> MkShoppingEntry "Banana" 1.1 3
buyOneMore :: ShoppingEntry -> ShoppingEntry
buyOneMore = todo
------------------------------------------------------------------------------
-- Ex 4: define a datatype Person, which should contain the age (an
-- Int) and the name (a String) of a person.
--
-- Also define a Person value fred, and the functions getAge, getName,
-- setAge and setName (see below).
data Person = PersonUndefined
deriving Show
-- fred is a person whose name is Fred and age is 90
fred :: Person
fred = todo
-- getName returns the name of the person
getName :: Person -> String
getName p = todo
-- getAge returns the age of the person
getAge :: Person -> Int
getAge p = todo
-- setName takes a person and returns a new person with the name changed
setName :: String -> Person -> Person
setName name p = todo
-- setAge does likewise for age
setAge :: Int -> Person -> Person
setAge age p = todo
------------------------------------------------------------------------------
-- Ex 5: define a datatype Position which contains two Int values, x
-- and y. Also define the functions below for operating on a Position.
--
-- Examples:
-- getY (up (up origin)) ==> 2
-- getX (up (right origin)) ==> 1
data Position = PositionUndefined
-- origin is a Position value with x and y set to 0
origin :: Position
origin = todo
-- getX returns the x of a Position
getX :: Position -> Int
getX = todo
-- getY returns the y of a position
getY :: Position -> Int
getY = todo
-- up increases the y value of a position by one
up :: Position -> Position
up = todo
-- right increases the x value of a position by one
right :: Position -> Position
right = todo
------------------------------------------------------------------------------
-- Ex 6: Here's a datatype that represents a student. A student can
-- either be a freshman, a nth year student, or graduated.
data Student = Freshman | NthYear Int | Graduated
deriving (Show,Eq)
-- Implement the function study, which changes a Freshman into a 1st
-- year student, a 1st year student into a 2nd year student, and so
-- on. A 7th year student gets changed to a graduated student. A
-- graduated student stays graduated even if he studies.
study :: Student -> Student
study = todo
------------------------------------------------------------------------------
-- Ex 7: define a datatype UpDown that represents a counter that can
-- either be in incresing or decreasing mode. Also implement the
-- functions zero, toggle, tick and get below.
--
-- NB! Define _two_ constructors for your datatype (feel free to name the
-- constructors however you want)
--
-- Examples:
--
-- get (tick zero)
-- ==> 1
-- get (tick (tick zero))
-- ==> 2
-- get (tick (tick (toggle (tick zero))))
-- ==> -1
data UpDown = UpDownUndefined1 | UpDownUndefined2
-- zero is an increasing counter with value 0
zero :: UpDown
zero = todo
-- get returns the counter value
get :: UpDown -> Int
get ud = todo
-- tick increases an increasing counter by one or decreases a
-- decreasing counter by one
tick :: UpDown -> UpDown
tick ud = todo
-- toggle changes an increasing counter into a decreasing counter and
-- vice versa
toggle :: UpDown -> UpDown
toggle ud = todo
------------------------------------------------------------------------------
-- Ex 8: you'll find a Color datatype below. It has the three basic
-- colours Red, Green and Blue, and two color transformations, Mix and
-- Invert.
--
-- Mix means the average of the two colors in each rgb channel.
--
-- Invert means subtracting all rgb values from 1.
--
-- Implement the function rgb :: Color -> [Double] that returns a list
-- of length three that represents the rgb value of the given color.
--
-- Examples:
--
-- rgb Red ==> [1,0,0]
-- rgb Green ==> [0,1,0]
-- rgb Blue ==> [0,0,1]
--
-- rgb (Mix Red Green) ==> [0.5,0.5,0]
-- rgb (Mix Red (Mix Red Green)) ==> [0.75,0.25,0]
-- rgb (Invert Red) ==> [0,1,1]
-- rgb (Invert (Mix Red (Mix Red Green))) ==> [0.25,0.75,1]
-- rgb (Mix (Invert Red) (Invert Green)) ==> [0.5,0.5,1]
data Color = Red | Green | Blue | Mix Color Color | Invert Color
deriving Show
rgb :: Color -> [Double]
rgb col = todo
------------------------------------------------------------------------------
-- Ex 9: define a parameterized datatype OneOrTwo that contains one or
-- two values of the given type. The constructors should be called One and Two.
--
-- Examples:
-- One True :: OneOrTwo Bool
-- Two "cat" "dog" :: OneOrTwo String
------------------------------------------------------------------------------
-- Ex 10: define a recursive datatype KeyVals for storing a set of
-- key-value pairs. There should be two constructors: Empty and Pair.
--
-- Empty represents an empty collection. It should have no fields.
--
-- Pair should have three fields, one for the key, one for the value,
-- and one for the rest of the collection (of type KeyVals)
--
-- The KeyVals datatype is parameterized by the key type k and
-- the value type v.
--
-- For example:
--
-- Pair "cat" True (Pair "dog" False Empty) :: KeyVals String Bool
--
-- Also define the functions toList and fromList that convert between
-- KeyVals and lists of pairs.
data KeyVals k v = KeyValsUndefined
deriving Show
toList :: KeyVals k v -> [(k,v)]
toList = todo
fromList :: [(k,v)] -> KeyVals k v
fromList = todo
------------------------------------------------------------------------------
-- Ex 11: The data type Nat is the so called Peano
-- representation for natural numbers. Define functions fromNat and
-- toNat that convert natural numbers to Ints and vice versa.
--
-- Examples:
-- fromNat (PlusOne (PlusOne (PlusOne Zero))) ==> 3
-- toNat 3 ==> Just (PlusOne (PlusOne (PlusOne Zero)))
-- toNat (-3) ==> Nothing
--
data Nat = Zero | PlusOne Nat
deriving (Show,Eq)
fromNat :: Nat -> Int
fromNat n = todo
toNat :: Int -> Maybe Nat
toNat z = todo