Рассмотрим функцию choose
на языке программирования Curry со спецификацией, что "(choose xs)
недетерминированно выбирает один элемент из списка xs
".
.реализовать его напрямую через два альтернативных недетерминированных правила:
choose :: [a] -> a
choose x:_ = x
choose _:xs = choose xs
Но в /usr/lib/curry-0.9.11/Success.curry из Muenster Curry Compiler , он определенс помощью вспомогательной функции:
choose (x:xs) = choosep x xs
where choosep x [] = x
choosep x (_:_) = x
choosep _ (x:xs) = choosep x xs
Какими могут быть преимущества (если таковые имеются) определения из поставляемого компилятором модуля?Являются ли эти 2 определения полностью эквивалентными (даже в некоторых сложных случаях с недетерминизмом и неопределенными значениями)? .. Является ли одно из них более эффективным в некоторых случаях?
ДОБАВЛЕНО: Более глубокое рассмотрение
cthom06(Спасибо!) Правильно указал, что мое определение вызовет попадание неопределенного значения в гораздо большее количество случаев (потому что мы будем пытаться вызывать эту функцию с аргументом пустого списка один раз для каждого нашего вызова «верхнего уровня» с изначально непустой список аргументов).(Хм, почему я не заметил это соображение сразу? ..) Это менее эффективно.
Но мне интересно: есть ли смысловые различия?Может ли разница быть важной в некоторых сложных контекстах?
Мы видим, что разница между двумя определениями - в случае непустых списков - в основном сводится к разнице между двумя потенциальными определениями для id
:
мое определение похоже на определение id
как:
id x = x
id _ = undefined
, а их определение похоже на определение id
обычным образом:
id x = x
(Итак, здесь прямолинейность обращена вспять.)
В каких контекстах это может быть важно?