【问题标题】:SML: how are constructors and functions distinguished?SML:如何区分构造函数和函数?
【发布时间】:2017-02-07 21:19:57
【问题描述】:

我有以下两个“函数”:is_three 和 SOME

fun is_three(number) =
    case numbers of
        3 => true
       | _ => false

当我写下以下两个语句时,我得到了这个:

is_three; 
val it = fn : int -> bool
SOME;
val it = fn : 'a -> 'a option

从表面上看,它们似乎都是返回值的函数。但是,如果我尝试在 case 语句中使用 is_three,我会得到以下信息:

stdIn:20.9-20.19 Error: non-constructor applied to argument in pattern: is_three

 fun are_threes(numbers) =
     case numbers of
         [] => true
       | is_three(x)::xs => true andalso are_threes(xs)
  1. case语句如何区分什么是构造函数和什么是函数
  2. 为什么不能在 case 语句中使用函数?

【问题讨论】:

    标签: pattern-matching sml


    【解决方案1】:

    1) 由于函数调用不是有效模式,因此没有什么可区分的。虽然确实像

    val x = FOO y
    

    如果没有进一步的上下文,就不可能判断FOO y 是函数还是数据类型构造函数(尽管命名约定会建议后者),在模式匹配的上下文中,不可能有歧义。如果FOO 是数据类型构造函数,则FOO y 是有效模式,但如果FOO 是函数则不是。

    2) 至于为什么,假设你可以让函数出现在模式中。假设你有以下两个函数

    fun square x = x*x
    fun cube x = x*x*x
    

    如果你可以定义这样的函数会怎样:

    fun f (square x) = x+1
    |   f (cube x) = x+2
    |   f _ = 3
    

    f 64 应该是什么? 64 是square 8 那么应该是 8+1 = 9 吗?还是应该是 4+2 = 6,因为cube 4 = 64?无论如何——编译器应该如何识别这种模式的实例?通常,即使函数g 是可计算的,如果给定值在g 的范围内,也可能无法确定。此外,请注意,使用与“模式”cube x 的模式匹配从值 64 恢复x = 4 需要反转函数cube。期望编译器反转任意函数是太过分了,尤其是因为它通常是不可能的。

    从某种意义上说,你所说的那种东西的弱形式是在 Haskell 中以 n+k patterns 的形式实现的。许多人认为这些是一个坏主意,最终从语言中删除。

    【讨论】:

    • 我猜的另一个选择是将它留给运行时而不是编译时。如果有两个选项可以匹配,则抛出运行时异常。
    • 附注你的意思是 4+2 = 6 在第二种情况下?
    • @Har 是的。谢谢。
    【解决方案2】:

    语言规范对函数和构造函数进行了区分。因此,即使构造函数的类型可能看起来像函数,构造函数和函数的使用方式也有不同的规则。构造函数可以用于 case 表达式,函数不能。

    在语言设计级别这样做的原因是构造函数和函数是不同的概念。构造函数是数据类型的“引入形式”,模式匹配是数据类型的“消除形式”。也就是说,构造函数是我们创建值的方式,模式匹配是我们“使用”值的方式。例如,我们使用[]:: 来构造一个值列表。要使用值列表,我们对列表进行模式匹配以提取头部和尾部。相反,函数是输入和输出之间的关系,可能包含也可能不包含构造函数和模式匹配。

    第二个问题比较难回答。首先,您在示例| is_three(x)::xs => true andalso are_threes(xs) 中的意思并不完全清楚。大概您的意思是将x::xsnumbers 匹配,如果is_three(x) 则成功。在这种解释下,您编写的模式匹配是不完整的(当 is_three 为假时会发生什么?)。该函数已经可以非常简洁地表达为

     fun are_threes(numbers) =
     case numbers of
         [] => true
       | x::xs => is_three(x) andalso are_threes(xs)
    

    Haskell 中有一个名为 view patterns 的语言扩展,它可以让您以模式编写函数。

    【讨论】:

    • 您还可以将数据类型定义视为定义一个同名的值构造函数和一个模式构造函数/值解构函数值构造函数在值域中充当函数,模式构造器/值解构器在模式域中工作。仅仅因为值构造函数具有函数类型,并不意味着函数通常具有与之匹配的隐式定义的模式构造函数。
    猜你喜欢
    • 2020-09-07
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多