Увеличение и уменьшение значения Haskell в списке

Я пытаюсь создать функцию

update_money :: Transaction -> Int -> Int

который принимает транзакцию и текущую сумму денег, которая у вас есть, и возвращает сумму денег, которая у вас есть после сделки. Таким образом, если транзакция покупает акцию, сумма денег, которую вы имеете, уменьшится, и если транзакция продает акции, сумма денег, которую вы имеете, увеличится. Например:

ghci> update_money ('B', 1, 10, "VTI", 5) 100
90
ghci> update_money ('S', 2, 10, "VTI", 5) 100
120

Это данные, которые были предоставлены:


type Transaction = (Char, Int, Int, String, Int) 
test_log :: [Transaction]    
test_log = [('B', 100, 1104, "VTI", 1),
('B', 200, 36, "ONEQ", 3),
('B', 50, 1223, "VTI", 5),
('S', 150, 1240, "VTI", 9),
('B', 100, 229, "IWRD", 10),
('S', 200, 32, "ONEQ", 11),
('S', 100, 210, "IWRD", 12)]

Вот моя попытка решить проблему:

update_money :: Transaction -> Int -> Int
update_money x (action, units, price, stocks, day) = 
    let money_type | action == 'B' = show (units - x)
                | action == 'S' = show (units + x)
                | otherwise     = "Incorrect, please input either B for bought or S for sold. " 
    in
        money_type

Однако при указании действия и (показать единицы) в одной строке я получаю преобразование типа, поэтому не уверен, как к этому подойти.

Возможно, вы захотите начать с размышлений о том, как бы вы переписали Python, чтобы использовать dict, который сопоставляет акцию с ее прибылью, а не отдельные profit* переменные.

chepner 13.11.2022 04:11

Кроме того, profit += (1 if transaction == 'B' else -1) * units * price_per_unit: заявление if не требуется. Чем меньше в вашем коде Python независимых операторов, тем ближе ваш код будет написан в функциональном стиле, после чего перевод на Haskell становится тривиальным.

chepner 13.11.2022 04:13

Да, и сигнатура типа, которую вы даете для update_money, обрабатывает только одну транзакцию, что уже намного проще, чем показанный вами эквивалент Python (который фактически делает несколько вызовов версии Python update_money, как вы ее описываете).

chepner 13.11.2022 04:15

Примеры, которые вы приводите для update_money, похоже, не заботятся о символе акции и о том, что является последним элементом транзакции.

chepner 13.11.2022 04:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
123
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я предполагаю, что способ, которым я подошел бы к этому в Haskell (и, если уж на то пошло, в Python), выглядел бы так:

import qualified Data.Map as M

trans lst = M.fromListWith (+)
    [ (stock, (if transaction == 'B' then id else negate) (units * price_per_unit))
    | (transaction, units, price_per_unit, stock, day) <- lst
    ]

Попробуйте в ghci:

> trans [('B', 100, 1104, "VTI", 1), ('B', 200, 36, "ONEQ", 3), ('B', 50, 1223, "VTI", 5), ('S', 150, 1240, "VTI", 9), ('B', 100, 229, "IWRD", 10), ('S', 200, 32, "ONEQ", 11), ('S', 100, 210, "IWRD", 12)]
fromList [("IWRD",1900),("ONEQ",800),("VTI",-14450)]

Привет, Даниэль, как бы ты сделал это без импорта функции?

user13744763 13.11.2022 05:21

@Stabbathehut Если бы мне не разрешили импортировать Data.Map, я бы сначала повторно реализовал Data.Map. Это отличная граница абстракции. Вы можете ознакомиться с его реализацией, начиная с самой актуальной функции, здесь.

Daniel Wagner 13.11.2022 17:52

Привет, Даниэль, не могли бы вы взглянуть на мой отредактированный код по вопросу, пожалуйста. Я немного застрял и был бы признателен за некоторые советы

user13744763 14.11.2022 00:04
Ответ принят как подходящий
update_money (action, units, price, stocks, day) sum = 
    let money_type  | action == 'B' = sum - units * price
                    | action == 'S' = sum + units * price
                    | otherwise     = 0
    in
        money_type

main = print $ update_money ('S', 2, 10, "VTI", 5) 100

вывод на моем ПК. Это работает хорошо.

Registering library for app2-0.1.0.0..
120

Другие вопросы по теме