2017-02-04 11 views
1

я две следующие «функции»: is_three и некоторыеSML: как выделяются конструкторы и функции?

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

Когда я пишу в следующих двух утверждениях я получаю это:

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

от поверхности они оба, кажется, функции, возвращаемые значения. Однако, если я пытаюсь использовать 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. как сазе можно выделить, Что конструктор и Что функция
  2. Почему функции не допускается в случае заявления?

ответ

2

1) Поскольку вызов функции не является допустимым шаблоном, нечего отличить. Хотя это правда, что в чем-то вроде

val x = FOO y 

не представляется возможным без дополнительного контекста, чтобы сказать, если FOO y функция или конструктор типа данных (хотя именование бы предложить последнее), в контексте сопоставления с образцом, нет никакой двусмысленности. FOO y является допустимым шаблоном, если FOO является конструктором типа данных, но не если 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. Кроме того, обратите внимание, что восстановление x = 4 из значения 64 с сопоставлением с шаблоном cube x потребует инвертировать функцию cube. Слишком много ожидать от компилятора инвертировать произвольные функции, тем более, что это вообще невозможно.

В некотором смысле, слабая форма того типа, о котором вы говорите, была реализована в Haskell в виде n+k patterns. Они считались многими плохой идеей и в конечном итоге были отброшены с языка.

+0

еще один вариант, я думаю, оставить его во время выполнения, а не компилировать время. Где, если есть два варианта, которые могут совпадать, затем отбросить исключение во время выполнения. – Har

+0

стр. вы имели в виду 4 + 2 = 6 во втором случае? – Har

+0

@ Хэр да. Благодарю. –

2

Спецификация языка делает различие между функциями и конструкторами. Поэтому, хотя тип конструкторов может выглядеть как функции, существуют различные правила использования конструкторов и функций. Конструкторы могут использоваться в случае выражений, функции не могут.

Причина этого на уровне проектирования языка заключается в том, что конструкторы и функции - это разные понятия. Конструкторы - это «форма ввода» типов данных, а шаблонные соответствия - это «форма исключения» типов данных. То есть, конструкторы - это то, как мы создаем ценности, сопоставление образцов - это то, как мы «используем» значения.Например, для построения списка значений мы используем [] и ::. Чтобы использовать список значений, мы сопоставляем шаблоны в списке, чтобы извлечь голову и хвост. Напротив, функция представляет собой соотношение между входами и выходами, которые могут содержать или не содержать конструкторы и шаблоны.

Второй вопрос - сложнее ответить. Во-первых, не совсем понятно, что вы имеете в виду в своем примере | is_three(x)::xs => true andalso are_threes(xs). Предположительно, вы имели в виду матч x::xs с numbers и преуспеть, если 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, который позволяет писать функции в шаблонах.

+1

Вы также можете просмотреть определения типа данных как определение конструктора * значения * и конструктора конструктора/значения * конструктора * с тем же именем. Конструктор * значения * действует как функция в стоимости земли, а конструктор/конструктор/конструктор * рисунка * работает в области рисунка. Просто потому, что конструктор значений имеет тип функции, это не означает, что функции обычно имеют неявно определенный конструктор шаблонов, который соответствует ему. –