Эти ответы (помимо решения Фреда Гандта) являются либо неправильными, либо неполными.
Предположим, что мне нужно variableName;
присвоить значение undefined
, и поэтому оно было объявлено таким образом, как var variableName;
, что означает, что он уже инициализирован; - Как я могу проверить, объявлено ли это ранее?
Или даже лучше - как я могу сразу проверить, существует ли «Book1.chapter22.paragraph37» с одним вызовом, но не вызывает опорную ошибку?
Мы делаем это, используя самый мощный оператор JasvaScript, оператор in.:
"[variable||property]" in [context||root]
>> true||false
. В периоды популярности AJAX я написал метод (позже названный) isNS (), который способна определять, существует ли пространство имен, включая глубокие тесты для имен свойств, таких как «Book1.chapter22.paragraph37» и многое другое.
Но поскольку он был ранее опубликован и из-за его большой важности он заслуживает чтобы опубликовать его в отдельном потоке, я не буду публиковать его здесь, но предоставит ключевые слова (javascript + isNS), которые помогут вам найти исходный код, поддерживаемый всеми необходимыми объяснениями.
В то время как implemenatations Haskell не мог бы сделать этого непосредственно как это внутренне, полезно думать об этом этот путь:)
[x | Just x <- myList]
... становится:
do
Just x <- myList
return x
..., который является:
myList >>= \(Just x) -> return x
относительно Вашего вопроса:
то, Что я не понимаю, как Haskell знает для вызова функции "сбоя"?
В-нотации, если шаблон, связывающий сбои (т.е. Just x
), то метод сбоя называют. Для вышеупомянутого примера это выглядело бы примерно так:
myList >>= \temp -> case temp of
(Just x) -> return x
_ -> fail "..."
Так, каждый раз у Вас есть соответствие шаблона в одноместном контексте, который может перестать работать, Haskell вставляет вызов в fail
. Испытайте его с IO:
main = do
(1,x) <- return (0,2)
print x -- x would be 2, but the pattern match fails
Эти правило для desugaring понимание списка требует выражения формы [ e | p <- l ]
(где e
выражение, p
шаблон, и l
выражение списка) ведут себя как [1 120]
let ok p = [e]
ok _ = []
in concatMap ok l
, Предыдущие версии Haskell имели понимания монады , которые были удалены из языка, потому что их было трудно считать и избыточный с do
- нотация. (Понимания списка избыточны также, но их не настолько трудно считать.) Я думаю desugaring [ e | p <- l ]
как , монада (или, чтобы быть точной, как монада с нулем ) привела бы к чему-то как [1 121]
let ok p = return e
ok _ = mzero
in l >>= ok
, где mzero
от MonadPlus
класс. Это очень близко к [1 122]
do { p <- l; return e }
, который desugars к [1 123]
let ok p = return e
ok _ = fail "..."
in l >>= ok
, Когда мы берем Монаду Списка, мы имеем
return e = [e]
mzero = fail _ = []
(>>=) = flip concatMap
, Т.е. 3 подхода (понимания списка, понимания монады, do
выражения) эквивалентны для списков.
Я не думаю, что синтаксис понимания списка имеет непосредственное отношение к факту, который Список ([]
), или Maybe
в этом отношении, оказывается, экземпляр Monad
класс типа.
понимания Списка действительно волшебство компилятора или сахар синтаксиса , но это возможно, потому что компилятор знает структуру []
тип данных.
Вот то, во что компилируется понимание списка: (Ну, я думаю, я на самом деле не проверял его по GHC)
xs = let f = \xs -> case xs of
Just x -> [x]
_ -> []
in concatMap f myList
, Как Вы видите, компилятор не должен звонить эти fail
функция, это может просто встроить пустой список, потому что это знает то, что список .
Интересно, это то, что синтаксис пониманий списка 'пропускает' отказы соответствия шаблона, используется в некоторых библиотеках, чтобы сделать универсальное программирование. Посмотрите пример в библиотека Uniplate .
<час> Редактирование: , О, и отвечать на Ваш вопрос, Вы не можете назвать Ваш select
функция с лямбдой, которую Вы дали ему. Это действительно перестанет работать при отказе соответствия шаблона при вызове его с Nothing
значение.
Вы могли передать его эти f
, функция от кода выше, но, чем [1 111] будет иметь тип:
select :: (a -> [b]) -> [a] -> [b]
, который прекрасно подходит, можно использовать эти concatMap
функция внутренне:-)
кроме того, который новый select
теперь имеет тип одноместного, связывают оператор для списков (с его зеркально отраженными аргументами):
(>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = concatMap f xs -- 'or as you said: concat (map f xs)