I have the following formula

fun foo 0 = [0] 
  | foo num = let val l =  (num mod 2)::foo(num div 2) in
           rev l
           end;

which is supposed to convert from decimal to binary.It has the following signature

val foo = fn : int -> int list

I am not sure where exactly I am getting things wrong as I am getting incorrect results.May someone help me figure out where I am making the error?

有帮助吗?

解决方案

The problem seems to be that you reverse the resulting list in every recursive step, instead of just once at the end.

Also, you probably need to map 0 to the empty list, otherwise you'll have one 0 too many in the end.

其他提示

Exactly what Andreas said. Now, the obvious way to get around this is to use a wrapper function:

fun f n =
let
  fun f' 0   = []
    | f' num = num mod 2 :: f' (num div 2)
in
  rev (f' n)
end

This works, but has the disadvantage of first building up the list, and then traversing it (the rev call). It also isn't tail-recursive. We can do better!

Instead of using reverse, we flip things around and use an accumulator:

fun g n =
let
  fun g' 0   acc = acc
    | g' num acc = g' (num div 2) (num mod 2 :: acc)
in
  g' n []
end

To understand the difference, let's see what happens if we run each of these on the number 4.

f 4 -> rev (f' 4)
    -> rev (4 mod 2 :: f' (4 div 2))
    -> rev (0 :: f' 2)
    -> rev (0 :: 2 mod 2 :: f' (2 div 2))
    -> rev (0 :: 0 :: f' 1)
    -> rev (0 :: 0 :: 1 mod 2 :: f' (1 div 2))
    -> rev (0 :: 0 :: 1 :: f' 0)
    -> rev (0 :: 0 :: 1 :: [])
    -> [1, 0, 0]

g 4 -> g' 4 []
    -> g' (4 div 2) (4 mod 2 :: [])
    -> g' 2 (0 :: [])
    -> g' (2 div 2) (2 mod 2 :: 0 :: [])
    -> g' 1 (0 :: 0 :: [])
    -> g' (1 div 2) (1 mod 2 :: 0 :: 0 :: [])
    -> g' 0 (1 :: 0 :: 0 :: [])
    -> [1, 0, 0]
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top