Ответ на вопрос edit:
так что мне делать для простого "прикрепить это к концу (или началу, что угодно) этого списка?" Сделать функцию, которая принимает список и BillingInfo в качестве аргументов, а затем возвращает список?
Ах, но уже есть "функция" для добавления элемента в список: это минус (:)
конструктор: -)
Таким образом, ваш существующий код будет работать нормально, если вы не используете одно и то же имя для двух разных переменных, поскольку привязка второго имени будет затенять (скрывать) первую.
ghci> let first_order_list = [Invoice 2345]
ghci> first_order_list
[Invoice 2345]
ghci> let second_order_list = CashOnDelivery : first_order_list
ghci> second_order_list
[CashOnDelivery, Invoice 2345]
Относительно второго редактирования:
Поскольку вы спрашиваете, как бы вы сделали что-то подобное в реальной программе, я бы сказал:
Если вы постоянно добавляете что-то в список, вы не хотите каждый раз придумывать новые имена для этого списка. Но ключевое слово здесь - «многократно», в императивном программировании вы бы использовали здесь цикл (и модифицировали некоторую переменную в цикле).
Поскольку это функциональное программирование, вы не можете использовать циклы, но вы можете использовать рекурсию. Вот как я написал бы программу, которая позволяет пользователю вводить заказы и собирать список:
main = do
orderList <- collectBillingInfos
putStrLn ("You entered these billing infos:\n" ++ show orderList)
collectBillingInfos :: IO [BillingInfo]
collectBillingInfos = loop []
where
loop xs = do
putStrLn "Enter billing info (or quit)"
line <- getLine
if line /= "quit"
then loop (parseBillingInfo line : xs)
else return xs
parseBillingInfo :: String -> BillingInfo
parseBillingInfo _ = CashOnDelivery -- Don't want to write a parser here
Подведем итог; функция loop
вызывает себя рекурсивно, каждый раз с новым элементом, добавляемым в список. Пока пользователь не введет «выход», он перестанет вызывать себя и вернет окончательный список.
Оригинальный ответ, относящийся к ленивой оценке:
Как уже говорили другие, это рекурсивное определение, делающее order_list
бесконечным списком, содержащим только CashOnDelivery
значений.
Хотя ленивая оценка не является причиной этого, она делает ее полезной.
Из-за ленивых вычислений вы можете использовать order_list
вот так:
ghci> take 3 order_list
[CashOnDelivery, CashOnDelivery, CashOnDelivery]
Если бы у вас не было ленивых вычислений, вызов take
прервался бы, потому что он сначала попытался бы оценить order_list
(что бесконечно).
Теперь, для order_list
это не очень полезно, но есть много других мест, где возможность программирования с бесконечными (или просто очень большими) структурами данных очень удобна.