Объявление типа функции в SML

Я новичок в ML, но в других языках, использующих вывод типов, я усвоил привычку опускать тип вещи всякий раз, когда вывод в правой части очевиден для читателя, и явно объявлять тип объекта. вещь всякий раз, когда вывод не очевиден для человека. Мне нравится это соглашение, и я хотел бы продолжить использовать его в своем коде ML.

У меня есть следующие примеры объявлений функций, которые эквивалентны:

fun hasFour      [] = false
  | hasFour (x::xs) = (x = 4) orelse hasFour xs

эквивалентно

val rec hasFour: int list -> bool =
 fn      [] => false
  | (x::xs) => (x = 4) orelse hasFour xs

Мне нравится последняя форма не только потому, что мне легче понять, какого типа функция, когда я ее читаю, но и потому, что она явно объявляет тип функции, и, следовательно, если я что-то напортачу в своей реализации, нет шансов случайно объявить что-то синтаксически допустимое, но неправильный тип, который потом будет труднее отлаживать.

Мой вопрос: я хочу использовать fun вместо val rec, потому что анонимные fn могут принимать только один параметр. Таким образом, последний метод синтаксически недействителен для такой функции, как int -> int -> bool. Есть ли способ явно объявить тип в fun? Или я назвал все предпочтительные альтернативы в этом посте и должен просто следовать одному из этих шаблонов? Единственный способ использовать fun с явным объявлением типа — это добавить объявление типа к каждому параметру в шаблоне, что довольно уродливо и ужасно, например:

fun hasFour ([]:int list):bool = false
  | hasFour            (x::xs) = (x = 4) orelse hasFour xs

Коллега показал мне код, следующий по такому шаблону:

fun hasFour      [] = false
  | hasFour (x::xs) = (x = 4) orelse hasFour xs

val _ = op hasFour: int list -> bool

Объявляя безымянную переменную и присваивая ей экземпляр функции с принудительным типом, мы эффективно достигаем желаемого результата, но val _ должна выглядеть как ниже полностью определенной функции, где это менее очевидно для человека-читателя, если только вы просто не получите привыкли к этому шаблону и научились его ожидать.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
310
1

Ответы 1

Недавно я задал очень похожий вопрос, Могу ли я аннотировать полный тип объявления fun?.

Ваше текущее решение было бы хорошим ответом на это.

У вас может быть несколько каррированных аргументов с несколькими fn, например. подобно:

val rec member : ''a -> ''a list -> bool =
    fn x => fn [] => false
             | y::ys => x = y orelse member x ys

Или вы можете сделать так, как делаете сейчас, или как предлагает Мэтт:

local
  fun member _ [] = false
    | member x (y::ys) = x = y orelse member x ys
in
  val member = member : ''a -> ''a list -> bool
end

Но комбинация использования fun и наличия полной подписи типа в списке первым пока неуловима.

Для производственного кода нормой является сбор сигнатур типов в подпись модуля. См. ML для работающего программиста, гл. 7: Подписи и абстракция, стр. 267-268. Хотя я предполагаю, что тогда вы захотите использовать Ocaml.

Другие вопросы по теме