Георги Наков, nakov.gl at gmail com
Марин Маринов, marinov.ms+tues at gmail com
Технологично училище "Електронни Системи"
23 Ноември 2016г.
- механизъм за създане на изброен тип -
enum
- механизъм за групиране на данни -
struct
- механизъм за създаване на изброен тип от групирани данни
- компилаторът се оплаква ако всички случаи не са обработени
- подпомагат описването на проблема като предварително очаквани ситуации
- предпазват от подаване на невалидни данни
Създаване на тип от предварително очаквани стойности. Компилаторът гарантира, че различна от изборените стойности не може да бъде присвоена на променлива от съответния тип.
data Answer = Yes | No
data CoinSides = Head | Tail
data DayOfWeek = Monday | Tuesday | Wednesday |
Thursday | Friday | Saturday | Sunday
scottishAnswer :: Answer -> String
scottishAnswer Yes = "Ay!"
scottishAnswer No = "Naw!"
> scottishAnswer Yes -- using the value `Yes`
"Ay!"
isWeekend :: DayOfWeek -> Bool
isWeekend Saturday = True
isWeekend Sunday = True
isWeekend _ = False
> isWeekend Monday -- using the value `Monday`
False
Също както tuples
ADTs могат да се използват за групиране на данни. Разликата е, че те добавят и "таг". По този начин две структури с еднакви подтипове, дори еднакви данни, се третират по различен начин.
Синтаксис:
data URL = URLPath String
-- | | |
-- Type Tag the value
Тагът също така се нарича Value constructor. Той се използва като функция и създава стойност от съответния тип.
data Password = PasswordText String
data Email = EmailText String
pwd :: Password
pwd = PasswordText "secure"
email :: Email
email = EmailText "[email protected]"
email' :: Email
email' = PasswordText "[email protected]" -- Error
Важно: Value конструкторът не е тип!
asEmail :: String -> EmailText -- Error!
asEmail str = EmailText str
-- Tag x y
data Point = Point Int Int
zero :: Point
zero = Point 0 0
translateX :: Int -> Point -> Point
translateX offset (Point x y) = Point (x + offset) y
Важно: В случая Point
се използва в 2 контекта - за създаване на стойност Point 0 0
и като тип zero :: Point
. Това е чест прийом, когато съществува само една дефиниция.
Силата на ADTs е в комбиниране на предходните две употреби. Така се създава комбинация от очаквани ситуации, които могат да носят и контекст (данни) със себе си.
-- longitude latitude
data Coordinates = Coordinates Int Int
-- city street #
data Address = TextAddress String String Int
| Location Coordinates
Value конструкторите могат да реферират към типа за създаване на вгнездени, рекурсивни структури.
data XMLElement = Text String
| Tag String XMLElement
stringify :: XMLElement -> String
stringify (Text text) = text
stringify (Tag tag el) = open ++ stringify el ++ close
where open = "<" ++ tag ++ ">"
close = "</" ++ tag ++ ">"
> stringify (Tag "book" (Tag "title" (Text "1984")))
"<book><title>1984</title></book>"
Тъй като ADT стойностите са предварително дефинирани, нормално очакване е да могат да бъдат сравнявани с ==
. Това по подразбиране не е така, но тъй като те са immutable Haskell може автоматично да генерира кода за сравнение. Това става чрез ключовата дума deriving
.
data Color = Red
| Green
| Blue
| RGB Int Int Int
deriving (Eq)
isBlack :: Color -> Bool
isBlack (RGB 0 0 0) = True
isBlack _ = False
> Red == Red
True
> RGB 11 22 33 == RGB 11 22 33
True
> isBlack (RGB 0 0 0)
True