I am trying to define a polymorphic function sum over the type T, where type T can be int, real or list of type T. The sum for the case of int and real should work as expected. For the case of list of T, it should return the sum of corresponding elements of two lists (the length of the lists should be same).
Examples:
sum (INT 2, INT 3) = INT 5
sum (REAL 2.3, REAL 3.4) = REAL 5.7
sum(L [2, 3, 4], L [3, 4, 5]) = L [5, 7, 9]
sum(L L([2, 3, 4], [2, 3, 4]), L ([3, 4, 5], [3, 4, 5]) = L ([5, 7, 9], [3, 4, 5])
The function which I wrote are as follows:
datatype T = INT of int | REAL of real | L of T list;
fun sum (x:T, x':T) = case (x, x') of
(INT n, INT n') => INT (n + n')
| (REAL n, REAL n') => REAL (n + n')
| (L (x :: xs), L (y :: ys)) => L ((sum (x, y)) :: (sum (L xs, L
ys))
| (_,_) => REAL (0.0);
But for the above function I was getting the error:
Constructor applied to the incorrect argument.
expects: _ * [??? list]
but got: _ * [???]
in: :: (sum (x, y), sum (L xs, L ys))
unhandled exception: Fail: compilation aborted: parseAndElaborate reported errors
Hence I changed my code by adding nil as below. As far as I perceived, the reason for the error was the fact that cons operator was trying to concatenate T (INT or REAL) to T (INT or REAL) in the end as (sum (x, y), sum (L xs, L ys)) will eventually get evaluated by recursive call to INT or REAL . Hence I changed my code by adding nil (empty list) in the end
fun sum (x:T, x':T) = case (x, x') of
(INT n, INT n') => INT (n + n')
| (REAL n, REAL n') => REAL (n + n')
| (L (x :: xs), L (y :: ys)) => L ((sum (x, y)) :: (sum (L xs,
L ys)) :: nil)
| (_,_) => REAL (0.0);
But for this case, it behaves correctly for INT and REAL but not for the polymorphic list. It behaves correctly for INT and REAL (as they are simpler to implement). For the list part, I guess there is some problem with the cons operator and am not able to figure out the solution. The test cases which I executed and their outputs are as follows:
sum (L([INT(1)]), L([INT(3)]));
val it = L [INT 4,L []] : T
sum (L([INT(1),INT(2)]), L([INT(3),INT(4)]));
val it = L [INT 4,L [INT #,L #]] : T
P.S: Please ignore the last case (,) => REAL (0.0) as I will handle the case of type mismatch later.