Dynamic scoping в Haskell
Oct. 30th, 2006 02:22 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Оказывается, есть и такая вещь в Хаскеле. Существует как расширение системы типов, есть ограничения, пользы большой не вижу, но пусть будет.
При dynamic scoping за связывание переменной отвечает вызывающий код, а не вызываемый.
Пример
В Haskell dynamic scoping реализуется с помощью Implicit parameters (IP). IP расписываются в Implicit Parameters: Dynamic Scoping with Static Types. Там объясняется как в HM-типизацию внедрить dynamic scoping. А вот как это выглядит практически:
Во первых, не забудем флажок -fimplicit-params, который включает поддержку IP.
Тип функции, использующей динамическм связанную переменную, использует имя этой переменной в своем контексте. Выглядит это так:
Т.е. в контексте типа мы должны определить все динамически связанные переменные в виде ?name :: type
Но подобные вещи допускаются только в контексте типа функции, поддержки классов и инстансов нет.
Использовать подобную функцию очень просто - переменные связываются с помощью let или where.
Рекурсивного поиска по умолчанию нет. Для того, чтобы определить, что переменную следует искать выше, надо аннотировать это явно:
Есть даже забавный пример по этому поводу:
Если мы раскомментируем строку с типом функции len_acc, то getLen "test" будет возвращать 4, иначе 0.
Конечно, использовать это я буду вряд ли, но читать было интересно. Тема легкая и нескучная, имхо.
При dynamic scoping за связывание переменной отвечает вызывающий код, а не вызываемый.
Пример
function foo()
{
print x; // x имеет динамическую область видимости.
}
function bar()
{
var x = 5;
foo(); // вот здесь x и привяжется.
}
В Haskell dynamic scoping реализуется с помощью Implicit parameters (IP). IP расписываются в Implicit Parameters: Dynamic Scoping with Static Types. Там объясняется как в HM-типизацию внедрить dynamic scoping. А вот как это выглядит практически:
Во первых, не забудем флажок -fimplicit-params, который включает поддержку IP.
Тип функции, использующей динамическм связанную переменную, использует имя этой переменной в своем контексте. Выглядит это так:
sortBy :: (a -> a -> Bool) -> [a] -> [a]
sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
sort = sortBy ?cmp
Т.е. в контексте типа мы должны определить все динамически связанные переменные в виде ?name :: type
Но подобные вещи допускаются только в контексте типа функции, поддержки классов и инстансов нет.
Использовать подобную функцию очень просто - переменные связываются с помощью let или where.
let ?cmp = (<) in sort xs
Рекурсивного поиска по умолчанию нет. Для того, чтобы определить, что переменную следует искать выше, надо аннотировать это явно:
least :: (?cmp :: a -> a -> Bool) => [a] -> a
least = head . sort
Есть даже забавный пример по этому поводу:
getLen :: [a] -> Int
getLen xs = let ?acc = 0 in len_acc xs
-- len_acc :: (?acc :: Int) => [a] -> Int
len_acc [] = ?acc
len_acc (x:xs) = let ?acc = ?acc + (1::Int) in len_acc xs
Если мы раскомментируем строку с типом функции len_acc, то getLen "test" будет возвращать 4, иначе 0.
Конечно, использовать это я буду вряд ли, но читать было интересно. Тема легкая и нескучная, имхо.
no subject
Date: 2006-10-30 11:29 am (UTC)Поэтому я решил воздержаться от использования этой штуки.
no subject
Date: 2006-10-30 11:45 am (UTC)