4
votes

I have a code which works fine:

let rec calculate s l acc =
    if length s = 0 then
        acc
    else
        if first s = l then
            calculate (rest s) l (acc+1)
        else
            calculate (rest s) (first s) acc

I want to rewrite it using pattern matching:

let rec calculate s l acc =
    function
    | _, _, _ when length s = 0 -> acc
    | _, _, _ when first s = l  -> calculate (rest s) l (acc+1)
    | _, _, _                   -> calculate (rest s) (first s) acc

But last function returns the error message:

  | _, _, _ when first s = l  -> calculate (rest s) l (acc+1)   -----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/Users/demas/temporary/stdin(512,36): error FS0001: Type mismatch. Expecting a 'a but given a 'b * 'c * 'd -> 'a The resulting type would be infinite when unifying ''a' and ''b * 'c * 'd -> 'a'

Why ?

1
This is a case where pattern matching doesn't really bring anything though. I would just use your original code, with elif instead of else if to avoid too deep indentation, but that's it. - Tarmil

1 Answers

6
votes

Keyword function implies that the last (implicit) parameter of the function calculate should be tuple containing 3 elements because you are matching on _, _, _ You could rewrite it as:

let rec calculate s l acc =
    match s, l, acc with
    | _, _, _ when length s = 0 -> acc
    | _, _, _ when first s = l  -> calculate (rest s) l (acc+1)
    | _, _, _                   -> calculate (rest s) (first s) acc

Also you could make pattern matching more clear rewriting it like:

let rec calculate s l acc =
    match (length s), (first s = l) with
    | 0, _    -> acc
    | _, true -> calculate (rest s) l (acc+1)
    | _, _    -> calculate (rest s) (first s) acc