Я пытаюсь создать функцию
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
Однако при указании действия и (показать единицы) в одной строке я получаю преобразование типа, поэтому не уверен, как к этому подойти.
Кроме того, profit += (1 if transaction == 'B' else -1) * units * price_per_unit
: заявление if
не требуется. Чем меньше в вашем коде Python независимых операторов, тем ближе ваш код будет написан в функциональном стиле, после чего перевод на Haskell становится тривиальным.
Да, и сигнатура типа, которую вы даете для update_money
, обрабатывает только одну транзакцию, что уже намного проще, чем показанный вами эквивалент Python (который фактически делает несколько вызовов версии Python update_money
, как вы ее описываете).
Примеры, которые вы приводите для update_money
, похоже, не заботятся о символе акции и о том, что является последним элементом транзакции.
Я предполагаю, что способ, которым я подошел бы к этому в 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)]
Привет, Даниэль, как бы ты сделал это без импорта функции?
@Stabbathehut Если бы мне не разрешили импортировать Data.Map
, я бы сначала повторно реализовал Data.Map
. Это отличная граница абстракции. Вы можете ознакомиться с его реализацией, начиная с самой актуальной функции, здесь.
Привет, Даниэль, не могли бы вы взглянуть на мой отредактированный код по вопросу, пожалуйста. Я немного застрял и был бы признателен за некоторые советы
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
Возможно, вы захотите начать с размышлений о том, как бы вы переписали Python, чтобы использовать
dict
, который сопоставляет акцию с ее прибылью, а не отдельныеprofit*
переменные.