Search code examples
smlfibonaccismlnjunbound

Getting error while defining a sequence of (all) Fibonacci numbers, in SML/NJ


here is my code:

val fibs =
 let
 val rec fibs_help =
 fn(n, next) => Cons(n, (fn()=>fibs_help(next, n+next)) )
 in
 fibs_help(0, 1)
 end;

val list = fibs(10)

And here is the error:

Error: unbound variable or constructor: Cons


Solution

  • The error message refers to a missing data type constructor, Cons. It is missing because you have no data type declaration in the mentioned code. You are probably missing a line that looks like:

    datatype 'a seq = Cons of 'a * (unit -> 'a seq)
    

    If you insert that declaration at the top of your code, you get a new error message:

    ! val list = fibs(10)
    !            ^^^^
    ! Type clash: expression of type
    !   int seq
    ! cannot have type
    !   'a -> 'b
    

    You get this error because you define fibs as a sequence of integers, but in the last line, you refer to fibs as a function that takes, presumably, a number of elements you wish to extract from that sequence. There is nothing wrong with the definition of the sequence. Here's how I would format the first part of the code:

    val fibs =
      let fun fibs_help (n, next) = Cons (n, fn () => fibs_help (next, n+next))
      in fibs_help(0, 1)
      end
    

    In order to extract a concrete amount of elements from this infinite sequence into e.g. a finite list requires a little more work. Write a function take (i, s) that produces a list of the first i elements of the sequence s:

    fun take (0, ...) = ...
      | take (i, Cons (n, subseq_f)) = ...
    

    The base case is when you want a list of zero elements from any sequence. Consider if/what you need to pattern match on the input sequence and what the result of this trivial case is. The recursive case is when you want a list of one or more elements from any sequence; do this by including the one element n in the result and solve a problem of the same structure but with a size one less using take, i and subseq_f.

    Once this function works, you can use it to get your list of ten elements:

    val ten_first = take (10, fibs)