Георги Наков, nakov.gl at gmail com
Марин Маринов, marinov.ms+tues at gmail com
Технологично училище "Електронни Системи"
30 Ноември 2016г.
Да дефинираме тип, който държи проста стойност от произволен тип:
data IntHolder = IBox Int
-- IBox 5
data CharHolder = CBox Char
-- CBox 'a'
data StringHolder = SBox [Char]
-- SBox "hi"
Отново същия проблем както и при функциите reverseInt :: [Int] -> [Int]
, reverseString :: [Char] -> [Char]
и тн.
Отново същото решение: вместо конкретен тип, ще използваме типов параметър a
- Box a
.
data Holder a = Box a
Важно: Освен в конструкторите на стойност (Box
), добавихме a
и в декларацията на типа - data Holder a
. Когато използваме типов параметър a
, Holder
вече не е валиден тип и не може да имаме стойности от него. Стойностите може да са Holder Int
, Holder Char
, Holder [Double]
.
data Holder a = Box a
ghci> :t Box True
Box True :: Holder Bool
ghci> :t Box "Hi"
Box "Hi" :: Holder [Char]
ghci> :t Box
Box :: a -> Holder a
Конструкторът на стойности Box
всъщност е полиморфична функция, която приема един аргумент от тип a
и връща Holder a
.
Много често използваме типови параметри, когато пишем контейнери за някакви стойности.
data List a = Empty | Cons a (List a)
data Tree v = EmptyNode | Node v (Tree v) (Tree v)
data Map k v = Map [(k, v)]
data Maybe a = Nothing | Just a
Най-често използваме Maybe a
, когато искаме да различаваме между валидни стойности от даден тип или грешка.
mySqrt :: Double -> Maybe Double
mySqrt x
| x < 0 = Nothing
| otherwise = Just (sqrt x)
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x