2014-09-24 3 views
4

Являются ли переменные в списке понятными неизменяемыми?Являются ли переменные в понимании списка неизменяемыми?

[x + 1 | x <- [1,2,3,4,5]] 

Например, в приведенном выше примере, x, кажется, изменить это значение. Это то, что на самом деле происходит, или что-то более сложное в работе здесь?

ответ

9

В Haskell нет переменных, а только значения, привязанные к именам.

Какого список понимание, как это будет заводится в самом деле монадический Список коды:

y = [x + 1 | x <- [1, 2, 3, 4, 5]] 
y = do 
    x <- [1, 2, 3, 4, 5] 
    return (x + 1) 

Тогда это дополнительно получает уменьшенные к использованию >>=:

y = [1, 2, 3, 4, 5] >>= (\x -> return (x + 1)) 

И тогда мы можем смотреть на определение для примера Monad для []:

instance Monad [] where 
    return x = [x] 
    list >>= f = concat (map f list) 
    -- uses the `concatMap` function in the actual definition 
    -- where `concatMap f list = concat (map f list)` 

Так замена return:

y = [1, 2, 3, 4, 5] >>= (\x -> [x + 1]) 

А потом >>=:

y = concat (map (\x -> [x + 1]) [1, 2, 3, 4, 5]) 

Теперь мы можем уменьшить его:

y = concat [[1 + 1], [2 + 1], [3 + 1], [4 + 1], [5 + 1]] 
y = concat [[2], [3], [4], [5], [6]] 
y = [2, 3, 4, 5, 6] 

Так как вы можете видеть, это не значит, что x переменная который изменяет значения, x становится аргументом функции лямбда, которая затем отображается на ta rget list.

+2

Отличный ответ, но два nitpicks: (a) «значения, связанные с именами» - это то, что переменные находятся в математике; говоря, что у Haskell нет переменных, я думаю, может только создать путаницу; (б), насколько я понимаю, компилятор фактически не превращает списки в монадический код; в основном, он пропускает шаги в вашем ответе, которые включают 'do',' >> = 'и' return'. Это полностью эквивалентно тому, что вы показываете. –

+0

@ LuisCasillas Это ручная волна, конечно. Что GHC на самом деле desugar это, это настраиваемая функция 'map'' f = \ ys -> case ys {[] -> []; (x: xs) -> (x + 1): f xs', затем примените это к '[1, 2, 3, 4, 5]', но базовое понятие одинаков. Я предполагаю, что там есть некоторые оптимизации для простых случаев, подобных этому, но в целом я считаю справедливым сказать, что GHC делает такого рода обезжиривание, даже если он не делает этого точного вида desugaring. – bheklilr

+0

@ LuisCasillas И я думаю, что правильно сказать, что у Haskell нет переменных в том смысле, что у Python есть переменные. Люди всегда вызывают 'IORef' и т. П., Но они все еще не являются переменными, чтобы получить значение от них или в них, вы выполняете операцию ввода-вывода, вы фактически не изменяете саму ссылку. Как только имя связано в Haskell, вы не сможете повторно связать его позже. Это имя может принимать разные значения в разных контекстах, но оно не изменяет и поэтому не меняется и не может удовлетворить основное требование быть переменной. – bheklilr

Смежные вопросы