Do those functions compile, and then crash anyway? I'd be interested to see examples. In my limited experience, if you can get your code to compile, it's pretty stable. Would be interesting to see counter examples.
Do those functions compile, and then crash anyway? I'd be interested to see examples. In my limited experience, if you can get your code to compile, it's pretty stable. Would be interesting to see counter examples.
fn 0 = return ()
main = fn 1
Giving an empty list to head/tail is another: main = head [] $ ghc --make test.hs -Wall
test.hs:1:1:
Warning: Pattern match(es) are non-exhaustive
In an equation for `fn':
Patterns not matched: #x with #x `notElem` [0#] Warning: Pattern match(es) are non-exhaustive
In an equation for `fn':
Patterns not matched:
[]
#x : _ with #x `notElem` [0#]
0# : (_ : _) makeChange :: Int -> [Int]
makeChange amount = loop 0 [200, 100, 25, 10, 5, 1] []
where loop total coins@(c:cs) solution
| total == amount = solution
| null coins = error "no solution"
| otherwise = if total + c > amount then
loop total cs solution
else
loop (total + c) coins (c : solution)
(I could make this a lot better by returning an [(Int, Int)] and by using integer division, but I wanted to just follow the algorithm described in the textbook.)To make sure that my code was correct, I wrote a QuickCheck property:
quickCheck (\(Positive n) -> sum (makeChange n) == n)
However, running this after compiling my file with GHC causes a stack overflow and I need to Ctrl+C out of the process.On the other hand, the exact same algorithm in OCaml runs extremely quick and without a hicup.
Amusingly, if you simply change the type to Integer -> [Integer], it all works ok. I suspect that since Integers have unbounded size, quickcheck only tests with reasonably small ones.
It runs just fine on my box with i = 2^32: 10s to completion or thereabouts.
However, the way this is written, the code has to construct the entire list in memory before it can print any of it out so for larger lists it is pretty much guaranteed to blow the stack and / or memory depending on the computational representation.
If it was using a snoclist or something then it could stream the output and perform the calculation in constance space, as it stands it has to hold on to the whole list of integers before outputting any of them.
I'm surprised that the OCaML version 'just worked' frankly: either a) the OP didn't use QuickCheck with their OCaML code or b) the OCaML QuickCheck doesn't bother testing across the whole Int space.