Требуются примеры использования first class function и patte
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.06 15:08
Оценка: 1 (1)
Когода кто-то пишет статьи о фунциональном программировании, то почему-то в качестве примеров всегда используются вещи вроде фунций Фибоначи и тому подобной бесполезной фигни.

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

Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).

Приветсвуются любые примеры.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Требуются примеры использования first class function и p
От: Gajdalager Украина  
Дата: 20.11.06 15:29
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Когода кто-то пишет статьи о фунциональном программировании, то почему-то в качестве примеров всегда используются вещи вроде фунций Фибоначи и тому подобной бесполезной фигни.


VD>Это приводит к тому, что у людей закрадывается сомнение, что данные возможности полезны в области математики, парсинга или еще какой-то специализированной области оторванной от жизни.


VD>Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).


VD>Приветсвуются любые примеры.

За! Правда, сам с ходу ничего предложить не могу, т.к. только учусь... Однако, хотелось, чтобы задачи были реализованы на ИЯ(С++, С#, Java, Python, Ruby), ФЯ (List, ML, Haskel, Erlang) и гибридных (Величайший Язык Современности, Scala, OCaml).. Думаю, достаточно бросить клич, и любители языков засыплют реализациями.. А потом все это склеить — и получим side-by-side сравнение, причем достаточно полезное, так как новичкам (таким, как я), легче будет увидеть, где лучше использовать функциональный подход, а где — императивный.
Re: Требуются примеры использования first class function и p
От: Mamut Швеция http://dmitriid.com
Дата: 20.11.06 16:12
Оценка:
VD>Приветсвуются любые примеры.

Для затравки quicksort и insertion sort на Эрланге сгодятся?

Как оказалось, не все знают, что такое quicksort. Только на прошлой неделе пришлось объяснять...
... << RSDN@Home 1.2.0 alpha rev. 655>>


dmitriid.comGitHubLinkedIn
Re: Требуются примеры использования first class function и p
От: Quintanar Россия  
Дата: 20.11.06 16:12
Оценка:
alpha blend:

let rseed = ref 1234;;

let random () =
    let nrs = (!rseed) * 214013 + 2531011 in
    rseed := nrs;
    (nrs lsr 16) land 0x7FFFFFFF;;

let rec lcreate func lst = function
     0 -> lst
|    n -> lcreate func ((func n)::lst) (n-1);;

let applay_mods mods h n =
    let (x,y) = (n mod h, n / h) in
    let ffun el f = f el x y in
    List.fold_left ffun (0,0,0,0) mods;;

let create_modifier w h _ =
    let x1 = (random ()) mod w
    and y1 = (random ()) mod h
    and x2 = (random ()) mod w
    and y2 = (random ()) mod h
    and cr = (random ()) mod 255
    and cg = (random ()) mod 255
    and cb = (random ()) mod 255
    and ca = (random ()) mod 255 in
    let (nx1,nx2) = if (x1 > x2) then (x2, x1-x2+1) else (x1, x2-x1+1)
    and (ny1,ny2) = if (y1 > y2) then (y2, y1-y2+1) else (y1, y2-y1+1) in
    fun ((r,g,b,a) as point) x y ->
        if ((x < nx1) || (x > nx2) || (y < ny1) || (y > ny2)) then point else 
        let nr = ((((cr-r)*ca) lsr 8) + r) land 255
        and ng = ((((cg-g)*ca) lsr 8) + g) land 255
        and nb = ((((cb-b)*ca) lsr 8) + b) land 255
        and na = (ca*a-((ca*a) lsr 8)) land 255 in
        (nr, ng, nb, na);;

let test_alpha_blend w h n =
    let mods = lcreate (create_modifier w h) [] n in
    lcreate (applay_mods mods h) [] (w*h);;

let main () =
    let w = 1000
    and h = 1000
    and n = 1000 in
    test_alpha_blend w h n;;

main ();;
Re: Требуются примеры использования first class function и p
От: Quintanar Россия  
Дата: 20.11.06 16:15
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Приветсвуются любые примеры.


Continuations in OCaml
Автор: Quintanar
Дата: 14.03.05
Re[2]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.06 16:44
Оценка:
Здравствуйте, Mamut, Вы писали:

VD>>Приветсвуются любые примеры.


M>Для затравки quicksort и insertion sort на Эрланге сгодятся?


Сгодится. Но примеры не к черту. Кому нужны супер тормозные реализации алгоритмов давно в оптимальном виде имеющиеся влюбой библиотеке?

Нужны просые примеры для демонстрации сути подхода. Лучше чето-нить из того что многие используют на прктике. Ну, там работа с данными, ГУИ (возможно) или еще что-то.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.06 16:44
Оценка:
Здравствуйте, Quintanar, Вы писали:

Я наверно не плохо изложил свою мысль. Ни в коем случае не нужны сложные алгоритмы. К тмоу же средний программист применяет альфа блэндинг еще резе чем Фибоначи.

Я сам в ступоре. Не раз испоьзовал те же FCF на практике, но как-то все это частные решения и как пример они лохо подходят.

А есть ли какие-нибудь совсем простые примеры (туториалы, что ли)? Может там поискать?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Требуются примеры использования first class function и p
От: Андрей Хропов Россия  
Дата: 20.11.06 17:06
Оценка: 40 (2)
Здравствуйте, VladD2, Вы писали:

Тут есть кое-что.

Хороший пример паттерн-матчинга — парсинг XML (да и текста тоже):
Собственно в туториалах к Немерле есть.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 20.11.06 17:09
Оценка:
VD>Я сам в ступоре.

так ты вопрос задал, навроде "приведите примеры использования циклов и полиморфизма"...
конечно сразу не догадаешься что тут вместо коллекций и фигур на экране в пример приводить...

тут наверно, как в императивщине — смотришь в чужой код, иногда думаешь, о! интересный оборот...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Требуются примеры использования first class function и p
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 20.11.06 17:15
Оценка:
VladD2,

VD>Приветсвуются любые примеры.


Конечно, хотелось бы универсальный пример, показывающий что:
1. Функции могут присвоены переменным.
2. Функции могут быть переданы как параметры.
3. Функции могут быть возвращены как значения.
4. Функции могут учавствовать в определении структур данных.

Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.

Тривиальный пример на четвёртый пункт — реализация хэш-таблицы. Мне не нравится он тем, что функция-параметр статическая (после определения не меняется) — не видно преимуществ по сравнению с указателями.

Более сложный пример подразумевает хранение в качестве ключа "символ", а в качестве значения какой-нибудь функции для последующей диспетчеризации, скажем реализации интерпретатора. Ничего не стоит реализовать определение новых операций с возможностью непосредственного исполнения.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: Требуются примеры использования first class function
От: Алексей П Россия  
Дата: 20.11.06 18:16
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, там работа с данными, ГУИ (возможно) или еще что-то.

Для ГУИ здорово подходят макросы Nemerle, пока дизайнера форм нет, и частичное применение. Вот про макросы (из реального проекта):
CreateNameValueDialog(150, this,
{
    | "Number of inputs" => udInputs : NumericUpDown ( Maximum = 8, Value = 1)
    | "Number of outputs" => udOutputs : NumericUpDown ( Minimum = 1, Maximum = 8, Value = 1)
})

Что делает, мне кажется, примерно ясно. Заодно может задекларировать поля в классе, если их нет.
Только использовать подобные фишки в качестве примеров не стоит наверно... А для FCF хороший пример — какой-нить парсер, или лучше преобразователь деревьев.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 20.11.06 18:59
Оценка:
LCR>Конечно, хотелось бы универсальный пример, показывающий что:
LCR>1. Функции могут присвоены переменным.
LCR>2. Функции могут быть переданы как параметры.
LCR>3. Функции могут быть возвращены как значения.
LCR>4. Функции могут учавствовать в определении структур данных.

LCR>Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.


вот здесь я не понял, то есть совсем не понял... (потому что математическая функция и программная функция, это 2 большие разницы)
можно чуть подробней, т.к. мне это очень интересно

LCR>Тривиальный пример на четвёртый пункт — реализация хэш-таблицы. Мне не нравится он тем, что функция-параметр статическая (после определения не меняется) — не видно преимуществ по сравнению с указателями.


LCR>Более сложный пример подразумевает хранение в качестве ключа "символ", а в качестве значения какой-нибудь функции для последующей диспетчеризации, скажем реализации интерпретатора. Ничего не стоит реализовать определение новых операций с возможностью непосредственного исполнения.


тут тоже не понял (в т.ч. что это за "символ"), но это в принципе, менее важно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Требуются примеры использования first class function
От: DrDred Россия  
Дата: 20.11.06 20:14
Оценка: 30 (1)
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Здравствуйте, VladD2, Вы писали:


АХ>Тут есть кое-что.


АХ>Хороший пример паттерн-матчинга — парсинг XML (да и текста тоже):

АХ>Собственно в туториалах к Немерле есть.

Вот аналогичный(?) пример на Scala
и вообще вот эта страница.
--
WBR, Alexander
Re: Требуются примеры использования first class function и p
От: wonderboy  
Дата: 20.11.06 20:51
Оценка:
Здравствуйте, VladD2, Вы писали:

Очень поддерживаю инициативу. Весьма интересная проблема.


VD>Это приводит к тому, что у людей закрадывается сомнение, что данные возможности полезны в области математики, парсинга или еще какой-то специализированной области оторванной от жизни.


А может быть так оно и есть?


VD>Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).


Мне понравился пример паттерн матчинга в Yet Another Haskell Tutorial. Раздел 7.4. Там и алгебраические типы есть, и задача не слишком оторванная от жизни (цвета в виде названий и в форме RGB). Да и вообще в этом тьюториале довольно много неплохих примеров, имхо.


VD>Приветсвуются любые примеры.


В какой форме готовить будем?


PS. Может быть у меня опыта маловато в ФП, но всеже красота функционального решения, имхо, особенно хорошо чувствуется именно в нетривиальных задачах.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Требуются примеры использования first class function и p
От: IT Россия linq2db.com
Дата: 21.11.06 00:25
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Приветсвуются любые примеры.


http://www.rsdn.ru/Forum/?mid=2151110
Автор: IT
Дата: 08.10.06
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re: Требуются примеры использования first class function и p
От: Tonal- Россия www.promsoft.ru
Дата: 21.11.06 06:24
Оценка: +1
Конечные автоматы — например разбор какого-нибудь лога, или поднятие XMLя через SAX.
Да и в GUI-е довольно частое явление.
Re: Требуются примеры использования first class function и p
От: Mirrorer  
Дата: 21.11.06 10:26
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).


VD>Приветсвуются любые примеры.


Можно подглядеть здесь.

А вообще примеры в Scala By Example слизаны с SICP
... << RSDN@Home 1.2.0 silent >>
Re[3]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.11.06 10:28
Оценка: 76 (13)
PhantomIvan,

LCR>>Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.


PI>вот здесь я не понял, то есть совсем не понял... (потому что математическая функция и программная функция, это 2 большие разницы)

PI>можно чуть подробней, т.к. мне это очень интересно

Да, совершенно верно (про выделенное). На этом примере хорошо видна разница между указателями на функции и ФВП. А также разница между Лиспом и не-Лиспом.

Итак, предположим, у нас есть некоторый вычислительный алгоритм, которому требуется для работы как сама функция f, так и её производная df (ну например, метод Ньютона, или скажем мы делаем свой собственный Maple ).

У нас есть путь классический — каждый раз когда нам понадобится запустить алгоритм для новой функции f, мы определяем новое тело для функции f и новое тело для функции df. Перекомпилируем. Запускаем... В случае Java/C# у нас есть костыли типа эмиттеров-загрузчиков.

В качестве альтернативы мы можем написать класс-интерпретатор, обёртку над AST, и операция дифференцирования будет расковыривать AST и генерировать новое T. У этого решения есть недостатки, в частности тот, что внешняя функция должна лезть в кишки интерпретатора. Придётся создавать абстрактный слой доступа к AST и т.п. Ну и этот велосипед конечно же будет подчиняться 10-му закону Гринспуна.

Вот путь Лиспа. Нам нужно просто написать функции типа (number? ...), (variable? ...).
(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
          (if (same-variable? exp var) 1 0))
        ((sum? exp)
          (make-sum (deriv (addend exp) var) 
                    (deriv (augend exp) var)))
        ((product? exp)
          (make-sum
            (make-product (multiplier exp)
                          (deriv (multiplicand exp) var))
            (make-product (deriv (multiplier exp) var)
                          (multiplicand exp))))
        (else
          (error "unknown expression type -- DERIV" exp))))

Тогда например
(deriv '(* (* x y) (+ x 3)) 'x)
(+ (* (* x y) (+ 1 0))
   (* (+ (* x 0) (* 1 y))
      (+  x 3)))

То, что выдала функция deriv — это полноценная функция. Её можно например передать в функцию рисования графиков, и будет нарисован график. Если полученное выражение кажется многословным, можно утоптать до минимального вида совершенно аналогичной функцией simplify. (В примере ниже будет одна из реализаций этой функции).

Вот путь Хаскеля. Поскольку в данном случае у нас уже нет волшебного порошка code is data is code , то придётся использовать алгебраические типы. Но с другой стороны это и преимущество, потому что уже работает паттерн-матчинг вместо (cond ...). Выглядеть это будет примерно так:
-- строительные блоки для выражений
infixl 5 :+
infixl 6 :*
data Exp = Num Integer
         | Var Sym
         | Exp :+ Exp
         | Exp :* Exp deriving (Eq,Show)

data Sym = X | Y deriving (Eq,Show)

main = do let exp = (Num 4 :* Var X :* Var X)
          let deriv = d exp X
          putStrLn $ "Original expression : " ++ (show exp)
          putStrLn $ "Derivative : " ++ (show $ simplify deriv)
          putStrLn $ "Derivative evaluated at X=10 : "
                     ++ (show $ eval (d exp X) [(X,10)])

-- взять производную
d (Num n)  x = Num 0
d (Var y)  x | x==y      = Num 1
             | otherwise = Num 0 
d (f :+ g) x = (d f x) :+ (d g x)
d (f :* g) x = (d f x) :* g :+ f :* (d g x)

-- вычислить выражение типа Exp...
eval (Num x) env = x
eval (Var x) env = case (lookup x env) of 
                        (Just n)  -> n
                        (Nothing) -> error $ "no variable "++(show x)++" in env"
eval (x :+ y) env = eval x env + eval y env
eval (x :* y) env = eval x env * eval y env

-- несколько алгебраических правил для упрощения
simp (x :+ y) | x == y = simp (Num 2):*x
simp ((Num 0) :+ x) = simp x
simp (x :+ (Num 0)) = simp x
simp ((Num x) :+ (Num y)) = Num (x+y)
simp (x :+ y) = simp x :+ simp y
simp ((Num 0) :* x) = Num 0
simp (x :* (Num 0)) = Num 0
simp ((Num 1) :* x) = simp x
simp (x :* (Num 1)) = simp x
simp ((Num x) :* (Num y)) = Num (x*y)
simp (x :* y) = simp x :* simp y
simp x = x

-- применять правила упрощения до тех пор, пока выражение не перестанет меняться
simplify x = let a = iterate simp x
                 fix = dropWhile (\(c,d)->c/=d) $ zip a (tail a)
             in (fst.head) fix

Вышеприведённый код выведет примерно следующее:
Original expression : (Num 4 :* Var X) :* Var X
Derivative : Num 2 :* (Num 4 :* Var X)
Derivative evaluated at X=10 : 80


Владу скорее всего пример не понравится, потому что слишком заумный и оторванный от жизни. А мне очень нравится, более того, могу сказать, что современные оптимизаторы в компиляторах — это функции типа simp, только естественно гораздо более сложные.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[4]: Требуются примеры использования first class function
От: Mirrorer  
Дата: 21.11.06 10:46
Оценка: 1 (1)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

Большое человеческое спасибо за пример на Haskell.
... << RSDN@Home 1.2.0 silent >>
Re[4]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 21.11.06 11:16
Оценка:
LCR>>>Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.

PI>>вот здесь я не понял, то есть совсем не понял... (потому что математическая функция и программная функция, это 2 большие разницы)

PI>>можно чуть подробней, т.к. мне это очень интересно

LCR>В качестве альтернативы мы можем написать класс-интерпретатор, обёртку над AST, и операция дифференцирования будет расковыривать AST и генерировать новое T. У этого решения есть недостатки, в частности тот, что внешняя функция должна лезть в кишки интерпретатора. Придётся создавать абстрактный слой доступа к AST и т.п. Ну и этот велосипед конечно же будет подчиняться 10-му закону Гринспуна.


вот, я как-нибудь подобное реализую, а что такое 10 закон Гринспуна? что все сложное ломается?

LCR>Вот путь Лиспа.


вот эта вот концепция: code is data is code очень даже подходит для символьных вычислений
но я как статически типизированный мэн, должен спросить: насколько реально это перетянуть к себе?
(как насчет: вычисляем в рантайм -> кидаем обратно в сорс?)

LCR>Вот путь Хаскеля.


он уже ближе к статике, не так ли?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.