F#作为匹配函数

时间:2016-11-15 10:05:42

标签: list f# match discriminator guard-clause

我创建了一个列表和列表列表的函数,并返回一个新的列表列表。

let rec calculator list SS =
  match (List.item(0) SS) with
  |[] -> []
  |_ -> match (validate list (List.item(0) SS)) with
        |(validate theCode list) -> List.append [(List.item(0) SS)] (calculator list (SS.[1..])) 
        |_ -> (calculator list (SS.[1..]))

validate是一个返回两个tupled整数的函数。例(1,1)

list是一个包含四个整数的列表

SS是一个包含四个整数的列表列表

theCode是一个包含四个整数的列表

我收到错误"模式鉴别器'验证'没有定义。"

也许这是一个愚蠢的问题但是我不知道答案。

是否不允许在匹配表达式中使用函数作为参数。或者这是完全不同的事情吗?

据我所知,两个验证函数将返回两个tupled整数,因此应该能够匹配。

2 个答案:

答案 0 :(得分:4)

如果你的问题是如何编译,那么你只需要一个小的改变 - 函数调用本身不是一个模式,所以你需要绑定一个值并使用when guard

let rec calculator list SS =
    match (List.item(0) SS) with
    | [] -> []
    | _  ->
        match (validate list (List.item(0) SS)) with
//        vvvvvvvvvv
        | x when x = (validate theCode list) ->
            List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
        | _ -> (calculator list (SS.[1..]))

但是,如果你的问题确实是" 什么是首选方法"那么虽然这个网站太过主观(IMO),但我是; ll将此提交作为我认为对此逻辑具有理想可读性的选项:

let rec calculator list (h::t) =
    if List.isEmpty h then h
    elif validate list h = validate theCode list then h::(calculator list t)
    else calculator list t

(这假定SS是F#列表,而不是System.Collections.Generic.List。)

答案 1 :(得分:4)

这实际上并不能解决如何实施when后卫的问题,因为@ildjarn answered适合你。

我认为你的图书馆功能实际上会更好。您要做的似乎是过滤掉未通过验证的元素,但也要停止在第一个空元素上。如果你可以保证你肯定想要遍历SS的每个元素,你可以简单地做

let calculator list = List.filter (fun s -> validate list s = validate theCode list)

如果你必须在空元素处停止,你可以定义一个在第一个空元素处切割列表的函数,如

let upToElement element list =
    let rec loop acc = function
        | [] -> List.rev acc
        | h :: t when h = element -> List.rev acc
        | h :: t -> loop (h :: acc) t
    loop [] list

然后你可以做

let calculator list =
    upToElement [] >> List.filter (fun s -> validate list s = validate theCode list)