Я думаю, что поскольку height
, sex
и age
по сути являются символами , вероятно, лучше представить их как символы. Таким образом, мы можем написать height <- ['T', 'S']
вместо height <- ["T", "S"]
или даже короче height <- "TS"
. Если мы создадим список String
с, мы не создадим String
, но - хорошо - список String
с.
Поскольку у вас есть доступ к символам, вы можете создать список из трех символов height
, sex
и age
, создав список : String
- это просто введите псевдоним для [Char]
.
Мы также можем сделать другие улучшения. Поскольку мы создаем список из трех элементов, длина всегда равна трем, поэтому нам не нужно проверять это позже в процессе, и мы можем сделать Human
с (я полагаю, вы смешали Person
и Human
) непосредственно.
Вы указываете state
в подписи, но это переменная типа. Это будет означать, что это может быть что угодно . Здесь, однако, это явно список Human
с, поэтому вам нужно изменить sgianture на (Human, [Human])
.
Наконец, нам не нужно создавать head
для получения первого элемента, но мы можем использовать сопоставление с образцом, и при этом мы не должны удалять этот элемент из списка: поскольку все элементы уникальны, все остальные элементы находятся в хвост (и никакой другой элемент не находится в хвосте):
func :: ([Human], [Human])
func = (x, state_) where
(x:state_) = [Human [height, sex, age] | height <- "TS", sex <- "MF", age <- "AC"]
Возможные улучшения
Я думаю, что моделирование может быть лучше, если вы определите Human
как:
data Human = Human Height Sex Age
data Height = Tall | Small
data Sex = Male | Female
data Age = Adult | Child
Делая это, вы ограничиваете число людей, которые могут быть построены по проекту . Действительно, прямо сейчас может оказаться, что функция содержит небольшую ошибку и выдает Human "ABC"
(символы не входят в «домен»), или Human "TM"
(слишком мало символов), или Human "AMT"
(порядок замены). Это может привести к большим проблемам в дальнейшем. Указывая домены и т. Д. В типе, функции просто не могут генерировать такие значения (хорошо, компилятор выдаст ошибку). Так что это дает вам «более сильные гарантии», что функция работает правильно Функция, конечно, может содержать семантическую ошибку .
Кроме того, определяя отдельные параметры, вы также обязываете каждого человека иметь эти три атрибута, и конструктор теперь curried .
Это также упростило бы процесс создания людей с помощью функций (<$>) :: f (a -> b) -> f a -> f b
и (<*>) :: f (a -> b) -> f a -> f b
:
Human <$> [Tall, Small] <*> [Male, Female] <*> [Adult, Child]