【问题标题】:How to pattern match nested lists?如何模式匹配嵌套列表?
【发布时间】:2013-02-03 15:06:27
【问题描述】:

在 sml/nj 中,我想创建一个函数,它接受一个非空列表的列表,并返回每个非空列表的第一个元素的列表。

fun get_first [] = []
 | get_first x::xs = (hd x)::get_first xs;
get_first: ('a list) list -> 'a list;

但是这不起作用... 有谁知道怎么回事?

【问题讨论】:

    标签: recursion pattern-matching smlnj ml


    【解决方案1】:

    您忘记在列表模式x::xs 周围加上括号,如下所示:

    fun get_first [] = []
      | get_first (x::xs) = (hd x)::get_first xs
    

    它不起作用的原因有点“复杂”。在 SML 中,列表只是被定义为一种数据类型和一些语法糖。它基本上看起来像这样

    datatype 'a list = nil | :: of ('a * 'a list)
    

    由于可以对数据类型构造函数进行模式匹配,因此可以对nil(通常写为[])和::进行模式匹配。
    但是,如果您不在它周围放置括号,那么它将被解释为该函数是模式匹配 3 个 curried 参数。这也许像这样更好地可视化

      | get_first (x) (::) (xs) = ....
    

    另外请注意,您可以使用地图功能轻松实现这一点

    fun get_first xs = map hd xs
    

    【讨论】:

    • 学究起来,由于::在标准库中被赋予了中缀状态,所以原始代码的第二个子句实际上被解析为(get_first x)::xs = ...,而这又是op:: (get_first x, xs) = ...的糖。换句话说,它试图定义一个名为::的函数。
    • @Andreas:如果它在函数体中,那将是正确的,但是由于它是函数子句的一部分,因此它的解析方式不同,如以下错误消息之一所示:get_first = (fn nil => nil | (x,_,xs) => hd :: get_first )。在这里可以看到第二个子句被解析为匹配三元组的模式。因此,它首先被解析为 3 个咖喱参数。
    • 耸耸肩。严格来说,这只是一个语法错误,因为中缀函数子句只允许原子模式作为参数(无论出于何种原因)。我不知道为什么 SML/NJ(我想这是您尝试过的)甚至尝试在这一点上进行类型检查。不管怎样,我看不出它的解释有什么意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 2014-04-21
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    相关资源
    最近更新 更多