Say есть стадион и номер строки является чем-то вроде А1-10, затем B1-10 и так далее до ZZHaskell типа пользовательских данных и reprsentation
Как не мне сделать пользовательский тип данных и использовать его для представляют место в Haskell?
Say есть стадион и номер строки является чем-то вроде А1-10, затем B1-10 и так далее до ZZHaskell типа пользовательских данных и reprsentation
Как не мне сделать пользовательский тип данных и использовать его для представляют место в Haskell?
Вы можете думать о своем перечислении как состоящую из трех частей
Первая и вторая части основаны на понятии «буква», поэтому давайте определим, что
data Letter
= La | Lb
| Lc | Ld
| Le | Lf
| Lg | Lh
| Li | Lj
| Lk | Ll
| Lm | Ln
| Lo | Lp
| Lq | Lr
| Ls | Lt
| Lu | Lv
| Lw | Lx
| Ly | Lz
deriving (Eq, Ord, Show)
Этот тип явно перечисляется вместо простого использования Char
, так что нам не нужно беспокоиться о различиях между нижним и верхним регистром или проблемами Char
, содержащих дополнительные вещи, такие как '-'
и '^'
. Поскольку я перечислял элементы в алфавитном порядке, автоподавленные экземпляры вроде Ord
ведут себя правильно.
Мы, вероятно, хотим воспользоваться тем фактом, что Letter
является подмножеством Char
, поэтому давайте тоже будем писать прогнозы.
- Это всегда работает, поскольку каждая буква является символом.
letterToChar :: Letter -> Char
letterToChar l = case l of
La -> 'a'
Lb -> 'b'
Lc -> 'c'
Ld -> 'd'
Le -> 'e'
Lf -> 'f'
Lg -> 'g'
Lh -> 'h'
Li -> 'i'
Lj -> 'j'
Lk -> 'k'
Ll -> 'l'
Lm -> 'm'
Ln -> 'n'
Lo -> 'o'
Lp -> 'p'
Lq -> 'q'
Lr -> 'r'
Ls -> 's'
Lt -> 't'
Lu -> 'u'
Lv -> 'v'
Lw -> 'w'
Lx -> 'x'
Ly -> 'y'
Lz -> 'z'
-- This one might fail since some characters aren't letters. We also do
-- automatic case compensation.
charToLetter :: Char -> Maybe Letter
charToLetter c = case Char.toLower of
'a' -> Just La
'b' -> Just Lb
'c' -> Just Lc
'd' -> Just Ld
'e' -> Just Le
'f' -> Just Lf
'g' -> Just Lg
'h' -> Just Lh
'i' -> Just Li
'j' -> Just Lj
'k' -> Just Lk
'l' -> Just Ll
'm' -> Just Lm
'n' -> Just Ln
'o' -> Just Lo
'p' -> Just Lp
'q' -> Just Lq
'r' -> Just Lr
's' -> Just Ls
't' -> Just Lt
'u' -> Just Lu
'v' -> Just Lv
'w' -> Just Lw
'x' -> Just Lx
'y' -> Just Ly
'z' -> Just Lz
_ -> Nothing -- default case, no match
Сейчас мы играем в одну игру с «цифрами от 1 до 10»
data Digit
= D1 | D2
| D3 | D4
| ...
deriving (Eq, Ord, Show)
digitToInt :: Digit -> Int
digitToInt = ...
intToDigit :: Int -> Maybe Digit
intToDigit = ...
Мы могли бы даже писать другие способы втягивания Int
к Digit
. Например, мы могли бы (1) принять абсолютное значение целого числа, а затем (2) взять его div
и mod
против 10 мест. Это приведет к присвоению Digit
и номеру строки.
intToDigitWrap :: Int -> (Int, Digit)
intToDigitWrap n = (row, dig) where
(row, dig0) = n `divMod` 10
-- we use an incomplete pattern match because we have an invariant
-- now that (dig0 + 1) is in [1, 10] so intToDigit always succeeds
Just dig = intToDigit (dig0 + 1)
И окончательный тип прост!
data Seat = Seat { letter1 :: Letter
, letter2 :: Maybe Letter
, digit :: Digit
} deriving (Eq, Ord, Show)
Тип Ord
снова полностью автоматически, как правильно Nothing
меньше Show x
для любого x
и записи заказа лексикографический. Мы также можем написать пример показать, что немного дружелюбнее очень просто
prettySeat :: Seat -> String
prettySeat s =
let l1 = [Char.toUpper $ letterToChar $ letter1 s]
l2 = case letter2 s of
Nothing -> ""
Just c -> [Char.toUpper $ letterToChar c]
dig = show (digitToInt (digit s))
in l1 ++ l2 ++ "-" ++ dig
По всей вероятности, способность впрыснуть Letter
и Digit
типы в их типов суперсут Char
и Int
соответственно почти наверняка пригодятся при написании кода позже ,
Я бы вывел 'letterToChar' и' charToLetter' из 'fromEnum' и' toEnum', плюс некоторые проверки границ. (Конечно, после 'получения (..., Enum)'). – chi
Я, вероятно, слишком серьезно рискнул бы опечатать ошибки. По какой-то причине я чувствовал, что его полное описание было бы иллюстративным. –
Используйте тип данных записи для хранения первой и второй частей отдельно. – Sibi
«До ZZ» означает, что после 'Z' вы попадаете в' AA', затем 'AB'? –
@BartekBanachewicz yes thats right – xcoder