The goal is to build a program to report the transactions for a particular stock in a human-readable format. For example, for our test data set, the transactions on the stock VTI will be printed as:
Bought 100 units of VTI for 1104 pounds each on day 1
Bought 50 units of VTI for 1223 pounds each on day 5
Sold 150 units of VTI for 1240 pounds each on day 9
Here is the test transaction code:
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)
]
For this, I thought is would be best to split each section into slices where they can be concatenated at the end.
--Converting transaction to string
transaction_to_string :: Transaction -> String
transaction_to_string (action: units: stocks: price: day) =
let display = action "Bought"
slice1 = units "of"
slice2 = stocks "for"
slice3 = price "on day"
slice4 = day
in
slice1 slice2 slice3 slice4
The error I am receiving is this. It is giving a type error but I am unsure why due to the type function used at the top:
• Couldn't match type ‘[Char]’ with ‘Char’
Expected: [Char]
Actual: [[Char]]
• In the second argument of ‘( )’, namely ‘slice4’
In the second argument of ‘( )’, namely ‘slice3 slice4’
In the second argument of ‘( )’, namely
‘slice2 slice3 slice4’
|
| slice1 slice2 slice3 slice4
CodePudding user response:
A first attempt:
transaction_to_string :: Transaction -> String
transaction_to_string (action, units, stocks, price, day) =
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tuple, not list
let display = show action "Bought" -- << convert non-strings using `show`
slice1 = show units "of" -- <<
slice2 = show stocks "for" -- <<
slice3 = price "on day"
slice4 = show day -- <<
in
display slice1 slice2 slice3 slice4
You could improve this by:
adding spaces in the right places
formatting the string better: the order of the concatenation seems a bit off (test it!)
properly handling
display
, perhaps using something like:let display | action == 'B' = "Bought" | action == 'S' = "Sold" | otherwise = "Uhh.. what?"
CodePudding user response:
Assuming Transaction
were not a type synonym, ideally you would make it an instance of Show
. For instance, if we used a record type.
data Transaction = Transaction {
action :: Char,
units :: Int,
stocks :: String,
price :: Int,
day :: Int
}
instance Show Transaction where
show (Transaction {action=a, units=u, stocks=s, price=p, day=d}) = str
where
a' = case a of
'B' -> "Bought"
'S' -> "Sold"
_ -> "Unknown action"
str = a' " " show u " units of " s
" at $" show p " on day " show d
Now:
Prelude> Transaction {action='B', units=100, stocks="FOO", price=56, day=7}
Bought 100 units of FOO at $56 on day 7