Re: haskell, изменяемое состояние
От: Курилка Россия http://kirya.narod.ru/
Дата: 22.01.08 11:33
Оценка: 2 (1)
Здравствуйте, lse, Вы писали:

lse>Скажем, нужно сделать функцию, на вход которой передается список по ссылке, функция его модифицирует.


lse>Для чего это нужно?


lse>Есть необходимо повесить на кнопку callback, который читает файл, конструирует объект и добавляет его в список объектов. Это спиок должен быть доступен в будущем и для других callback-ов. Ответ на приведенный выше вопрос интересует вне зависимости от того, какое решение проблемы будет предложено.


Предположу, что тут было бы полезно заюзать паттерн ФП Zipper, правда статья в вики несколько заморочна на мой взгляд, лучше статью Хуэта сразу смотреть — по мне там много понятней.
Re[7]: haskell, изменяемое состояние
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 22.01.08 14:18
Оценка: 2 (1)
Здравствуйте, lse, Вы писали:

lse>Здравствуйте, lomeo, Вы писали:


L>>Ну, надо было, наверное, объяснить, что сам вопрос лишён смысла, потому что в Хаскеле нет последовательности действий, поэтому понятие "модификация" бессмысленно, если рассматривать функции как математические.


lse>Я знаю, что в чистых функциях все именно так.


L>>А тут и зиппер не нужен, цикл с состоянием (StateT MyState IO) в котором проверяются сигналы (скажем из входного потока) и передаются на обработчики (callback-и). Тогда callback может делать что-то вроде


L>>
L>>myCallback :: Signal -> StateT MyState IO ()
L>>myCallback signal = do
L>>    object <- liftIO $ getObjectFromFile (fileNameFromSignal signal)
L>>        objectList <- gets myObjects
L>>        modify $ updateObjectList (object : objectList)
L>>


lse>Если конкретнее — то это wxHaskell.


lse>Нужны пояснения.


lse>getObjectFromFile (fileNameFromSignal signal) — возвращает объект, соотв. файлу


lse>object <- liftIO $ .... — это что такое? что за liftIO?


Мы работает в StateT MyState IO, потому что нам надо работать с IO (работа с файлом). Для того, чтобы позвать обёрнутый трансформером IO делают liftIO. В данном случае он имеет тип IO Object -> StateT MyState IO Object, т.к. getObjectFromFile (fileNameFromSignal signal) :: IO Object.

lse>Откровенно говоря, все, что мне нужно — это схематчески набросанный пример с окном, на котором кнопка, при нажатии на кнопку к глобальной коллекции происходит добавление нового числа. Один раз нажали — [1], второй раз нажали — [1,2], третий раз — [1,2,3].


Что то вроде

do ref <- newIORef []
    f <- frame [text := "lse test"]
    incBtn  <- button f [text := "Inc", on command := modifyIORef ref updateMyList]
    printBtn <- button f [text := "Print", on command := (readIORef >>= print . reverse)]
where
    updateMyList xs = (length xs) : xs


lse>а как на счет этого?


Замечательно, это именно то, что я и deniok тебе давали
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: haskell, изменяемое состояние
От: deniok Россия  
Дата: 22.01.08 14:48
Оценка: 2 (1)
Здравствуйте, lse, Вы писали:



lse>Как тогда хранить list между вызовами callback-ов?

lse>Я знаю, что нет identity. Но не предсталвяю, как вот в этом случае можно обойтись без модификации.

В WxHaskell действительно никак.

Unlike more functional GUI libraries, wxHaskell does not provide a model for state management and uses simple mutable variables to communicate state across different event handlers. (Note: this is a concious design decision – as functional GUI interfaces are still very much a research area, we want to provide a full fledged GUI library using simple IO first, than try to build good functional interfaces on top of that).

отсюда

Поэтому в WxHaskell это делается по-императивному: там для этого есть
type Var a = IORef a

здесь

Посмотри также Graphics.UI.WX.Variable, возможно это будет несколько удобнее.

Пример использования Var — игра Bouncing balls отсюда.

А более "функциональные" решения для state management сделано в надстройке над WxHaskell, wxFruit.
Re[7]: haskell, изменяемое состояние
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 22.01.08 13:22
Оценка: 1 (1)
Здравствуйте, Курилка, Вы писали:

К>Знаешь, всё это терминологический спор, т.е. по сути изоморфные вещи, если погрубей — "те же яйца, только сбоку".


С другой стороны этот спор изоморфен приятной дружеской беседе, в которой мы в меру своих сил пытаемся помочь коллеге, показывая разные взгляду на одну проблему

К>Реально пусть товарищ попробует то, что ему будет понятней и по скоросте внятней.


+1.

Хорошо было бы на саму задачу посмотреть, чтобы показать пути решения, а то у lse императивные представления (модификация).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: haskell, изменяемое состояние
От: Курилка Россия http://kirya.narod.ru/
Дата: 22.01.08 13:08
Оценка: +1
Здравствуйте, lomeo, Вы писали:

lse>>>>строится оно в рантайме заново или нет меня в этом случае не интересует, т к оно identity. Можно пример функции, на вход которой приходит список, а функция его модифицирует.


L>>>Нет


К>>Дак чегож так сразу, а зиппер на что?


L>Ну, надо было, наверное, объяснить, что сам вопрос лишён смысла, потому что в Хаскеле нет последовательности действий, поэтому понятие "модификация" бессмысленно, если рассматривать функции как математические.


L>А тут и зиппер не нужен, цикл с состоянием (StateT MyState IO) в котором проверяются сигналы (скажем из входного потока) и передаются на обработчики (callback-и). Тогда callback может делать что-то вроде


L>
L>myCallback :: Signal -> StateT MyState IO ()
L>myCallback signal = do
L>    object <- liftIO $ getObjectFromFile (fileNameFromSignal signal)
L>        objectList <- gets myObjects
L>        modify $ updateObjectList (object : objectList)
L>


Знаешь, всё это терминологический спор, т.е. по сути изоморфные вещи, если погрубей — "те же яйца, только сбоку".
Реально пусть товарищ попробует то, что ему будет понятней и по скоросте внятней.
haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 11:18
Оценка:
Скажем, нужно сделать функцию, на вход которой передается список по ссылке, функция его модифицирует.

Для чего это нужно?

Есть необходимо повесить на кнопку callback, который читает файл, конструирует объект и добавляет его в список объектов. Это спиок должен быть доступен в будущем и для других callback-ов. Ответ на приведенный выше вопрос интересует вне зависимости от того, какое решение проблемы будет предложено.
Re: haskell, изменяемое состояние
От: deniok Россия  
Дата: 22.01.08 11:32
Оценка:
Здравствуйте, lse, Вы писали:

lse>Скажем, нужно сделать функцию, на вход которой передается список по ссылке, функция его модифицирует.


Data.IORef

lse>Для чего это нужно?


lse>Есть необходимо повесить на кнопку callback, который читает файл, конструирует объект и добавляет его в список объектов. Это спиок должен быть доступен в будущем и для других callback-ов. Ответ на приведенный выше вопрос интересует вне зависимости от того, какое решение проблемы будет предложено.


Не понял, чем тебе обычные списки не угодили. Ты же не думаешь, надеюсь, что в
newList = myCoolObject : oldList

newList в рантайме строится заново?
Re[2]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 11:54
Оценка:
Здравствуйте, deniok, Вы писали:

D>Здравствуйте, lse, Вы писали:


lse>>Скажем, нужно сделать функцию, на вход которой передается список по ссылке, функция его модифицирует.


D>Data.IORef


можно пример

lse>>Для чего это нужно?


lse>>Есть необходимо повесить на кнопку callback, который читает файл, конструирует объект и добавляет его в список объектов. Это спиок должен быть доступен в будущем и для других callback-ов. Ответ на приведенный выше вопрос интересует вне зависимости от того, какое решение проблемы будет предложено.


D>Не понял, чем тебе обычные списки не угодили. Ты же не думаешь, надеюсь, что в

D>
D>newList = myCoolObject : oldList
D>

D>newList в рантайме строится заново?

строится оно в рантайме заново или нет меня в этом случае не интересует, т к оно identity. Можно пример функции, на вход которой приходит список, а функция его модифицирует.
Re[2]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 11:55
Оценка:
К>Предположу, что тут было бы полезно заюзать паттерн ФП Zipper, правда статья в вики несколько заморочна на мой взгляд, лучше статью Хуэта сразу смотреть — по мне там много понятней.

спасибо, буду смотреть. по первой ссылке ничего не понял, разбираюсь со второй.
Re[3]: haskell, изменяемое состояние
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 22.01.08 12:23
Оценка:
Здравствуйте, lse, Вы писали:

D>>Data.IORef


lse>можно пример


do ref <- newIORef [1,2,3]
var <- readIORef ref
print var
let var = 0:var
print var
writeIORef var ref
var <- readIORef ref
print var

Если не хочется залезать в IO, тоже самое можно сделать с STRef, например.

lse>>>Для чего это нужно?


lse>строится оно в рантайме заново или нет меня в этом случае не интересует, т к оно identity. Можно пример функции, на вход которой приходит список, а функция его модифицирует.


Нет
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: haskell, изменяемое состояние
От: Курилка Россия http://kirya.narod.ru/
Дата: 22.01.08 12:28
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Здравствуйте, lse, Вы писали:


lse>>строится оно в рантайме заново или нет меня в этом случае не интересует, т к оно identity. Можно пример функции, на вход которой приходит список, а функция его модифицирует.


L>Нет


Дак чегож так сразу, а зиппер на что?
Re[3]: haskell, изменяемое состояние
От: deniok Россия  
Дата: 22.01.08 12:32
Оценка:
Здравствуйте, lse, Вы писали:

D>>Data.IORef


lse>можно пример

test ss = do rs <- newIORef ss
             old <- readIORef rs
             writeIORef rs ('H' : tail old)
             new <- readIORef rs
             return (old, new)

GHCi:
*Main1> test "hello"
("hello","Hello")



lse>строится оно в рантайме заново или нет меня в этом случае не интересует, т к оно identity. Можно пример функции, на вход которой приходит список, а функция его модифицирует.


Это не идиоматично для Хаскелла. В нём нет identity. IORef в этом смысле некоторая затычка для введения ссылочной семантики в монаде IO, то есть для работы с внешними объектами. Если хочется "чистого" решения — лучше действительно зиппер использовать. Уточнил бы задачу...
Re[4]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 12:41
Оценка:
Здравствуйте, deniok, Вы писали:

D>Здравствуйте, lse, Вы писали:


D>>>Data.IORef


lse>>можно пример

D>
D>test ss = do rs <- newIORef ss
D>             old <- readIORef rs
D>             writeIORef rs ('H' : tail old)
D>             new <- readIORef rs
D>             return (old, new)
D>

D>GHCi:
D>
D>*Main1> test "hello"
D>("hello","Hello")
D>



lse>>строится оно в рантайме заново или нет меня в этом случае не интересует, т к оно identity. Можно пример функции, на вход которой приходит список, а функция его модифицирует.


D>Это не идиоматично для Хаскелла. В нём нет identity. IORef в этом смысле некоторая затычка для введения ссылочной семантики в монаде IO, то есть для работы с внешними объектами. Если хочется "чистого" решения — лучше действительно зиппер использовать. Уточнил бы задачу...


я хотел написать, что оно не identity, опечатка. IO не подходит кажется, т к мне нужно именно модифицировать список, добавляя к нему элементы.

вот что нужно.

приблизительно так

есть кнопка, на нее:
onClick = onclick list

в onclick читается файл, преобразуется в объект-модель, затем этот объект к list добавляется ввиде элемента. list — глобальный список. все. почитал по ссылкам, zipper по описанию сюда подходит, только вот пользоваться им еще научиться надо.
Re[5]: haskell, изменяемое состояние
От: deniok Россия  
Дата: 22.01.08 12:51
Оценка:
Здравствуйте, lse, Вы писали:

lse>вот что нужно.


lse>приблизительно так


lse>есть кнопка, на нее:

lse>onClick = onclick list

lse>в onclick читается файл, преобразуется в объект-модель, затем этот объект к list добавляется ввиде элемента. list — глобальный список. все. почитал по ссылкам, zipper по описанию сюда подходит, только вот пользоваться им еще научиться надо.


Я пока не понял, чем обычный список не подходит, и что там дальше будут за модифицирующие callback'и. Но, да, если важна эффективная модификация по месту, то зипперы рулят. Только в любом случае вызов f :: ... -> Cont a -> Cont a с точки зрения Хаскелла порождает новое значение типа Cont a. Другое дело — гарантии сложности O(1).
Re[4]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 12:54
Оценка:
Здравствуйте, deniok, Вы писали:

D>Здравствуйте, lse, Вы писали:


D>>>Data.IORef


lse>>можно пример

D>
D>test ss = do rs <- newIORef ss
D>             old <- readIORef rs
D>             writeIORef rs ('H' : tail old)
D>             new <- readIORef rs
D>             return (old, new)
D>

D>GHCi:
D>
D>*Main1> test "hello"
D>("hello","Hello")
D>



а пример не катит. нужно не измененный список возвращать, а именно модифицировать переданный по ссылке.
Re[5]: haskell, изменяемое состояние
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 22.01.08 12:55
Оценка:
lse>>>строится оно в рантайме заново или нет меня в этом случае не интересует, т к оно identity. Можно пример функции, на вход которой приходит список, а функция его модифицирует.

L>>Нет


К>Дак чегож так сразу, а зиппер на что?


Ну, надо было, наверное, объяснить, что сам вопрос лишён смысла, потому что в Хаскеле нет последовательности действий, поэтому понятие "модификация" бессмысленно, если рассматривать функции как математические.

А тут и зиппер не нужен, цикл с состоянием (StateT MyState IO) в котором проверяются сигналы (скажем из входного потока) и передаются на обработчики (callback-и). Тогда callback может делать что-то вроде

myCallback :: Signal -> StateT MyState IO ()
myCallback signal = do
    object <- liftIO $ getObjectFromFile (fileNameFromSignal signal)
        objectList <- gets myObjects
        modify $ updateObjectList (object : objectList)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 12:59
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Здравствуйте, lse, Вы писали:


D>>>Data.IORef


lse>>можно пример


L>do ref <- newIORef [1,2,3]

L> var <- readIORef ref
L> print var
L> let var = 0:var
L> print var
L> writeIORef var ref
L> var <- readIORef ref
L> print var

отлично, могу я передать var в функцию editVar, которая меняет var, причем не возвращает его, а именно, модифицирует то, что есть, чтобы потом изменения наружу торчали?
Re[5]: haskell, изменяемое состояние
От: deniok Россия  
Дата: 22.01.08 13:09
Оценка:
Здравствуйте, lse, Вы писали:

lse>а пример не катит. нужно не измененный список возвращать, а именно модифицировать переданный по ссылке.


old и new я ввёл, чтобы продемонстрировать, что rs — мутирует внутри IO. По сути достаточно было
test ss = do rs <- newIORef ss
             modifyIORef rs (\xs -> 'H' : tail xs)
             readIORef rs

Я же не напрямую твою задачу решаю, а демонстрирую как создавать модифицируемую ссылку на список.
Re[5]: haskell, изменяемое состояние
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 22.01.08 13:22
Оценка:
Здравствуйте, lse, Вы писали:

lse>отлично, могу я передать var в функцию editVar, которая меняет var, причем не возвращает его, а именно, модифицирует то, что есть, чтобы потом изменения наружу торчали?


Нет.

В Haskell-е нет переменных, там только значения — поэтому там ничего нельзя "модифицировать". Чтобы была глобальная область видимости и изменяемость, воспользуйся ссылками.

Для того, чтобы понять это, попробуй сам написать реализацию ссылок на чистом Хаскеле, возьми за основу монаду состояния, тогда ты поймёшь о чём идёт речь.

Посмотри на это по другому — а зачем тебе менять именно var, а не ref, или выбрать вообще другой путь?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 13:37
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Ну, надо было, наверное, объяснить, что сам вопрос лишён смысла, потому что в Хаскеле нет последовательности действий, поэтому понятие "модификация" бессмысленно, если рассматривать функции как математические.


Я знаю, что в чистых функциях все именно так.

L>А тут и зиппер не нужен, цикл с состоянием (StateT MyState IO) в котором проверяются сигналы (скажем из входного потока) и передаются на обработчики (callback-и). Тогда callback может делать что-то вроде


L>
L>myCallback :: Signal -> StateT MyState IO ()
L>myCallback signal = do
L>    object <- liftIO $ getObjectFromFile (fileNameFromSignal signal)
L>        objectList <- gets myObjects
L>        modify $ updateObjectList (object : objectList)
L>


Если конкретнее — то это wxHaskell.

Нужны пояснения.

getObjectFromFile (fileNameFromSignal signal) — возвращает объект, соотв. файлу

object <- liftIO $ .... — это что такое? что за liftIO?

Откровенно говоря, все, что мне нужно — это схематчески набросанный пример с окном, на котором кнопка, при нажатии на кнопку к глобальной коллекции происходит добавление нового числа. Один раз нажали — [1], второй раз нажали — [1,2], третий раз — [1,2,3].

а как на счет этого?

main = do
    rs <- newIORef [1,2,3]
    test rs

test rs = do
oldRs <- readIORef rs
writeIORef rs ('1' : oldRs)
return rs
Re[7]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 13:44
Оценка:
lse>
lse>main = do
lse>    rs <- newIORef [1,2,3]
lse>    test rs

lse>test rs = do
lse>oldRs <- readIORef rs
lse>writeIORef rs ('1' : oldRs)
lse>return rs
lse>


ошибка — вот так:

main = do
rs <- newIORef [1,2,3]
test rs

test rs = do
oldRs <- readIORef rs
writeIORef rs ('1' : oldRs)
return


по идее ведь rs должен изменитьсяи в main?
Re[7]: haskell, изменяемое состояние
От: deniok Россия  
Дата: 22.01.08 13:46
Оценка:
Здравствуйте, lse, Вы писали:


lse>Откровенно говоря, все, что мне нужно — это схематчески набросанный пример с окном, на котором кнопка, при нажатии на кнопку к глобальной коллекции происходит добавление нового числа. Один раз нажали — [1], второй раз нажали — [1,2], третий раз — [1,2,3].


Ну и напиши модификатор
modList lst@(x:xs) = (x+1):lst

(Добавляют обычно в голову, если обязательно в хвост — добавь reverse, например.)
И дёргай его при каждом нажатии.

А глобальной коллекции не бывает — старую передаёшь, новую получаешь. Нет объектов с identity
Re[8]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 14:04
Оценка:
Здравствуйте, deniok, Вы писали:

D>Здравствуйте, lse, Вы писали:



lse>>Откровенно говоря, все, что мне нужно — это схематчески набросанный пример с окном, на котором кнопка, при нажатии на кнопку к глобальной коллекции происходит добавление нового числа. Один раз нажали — [1], второй раз нажали — [1,2], третий раз — [1,2,3].


D>Ну и напиши модификатор

D>
D>modList lst@(x:xs) = (x+1):lst
D>

D>(Добавляют обычно в голову, если обязательно в хвост — добавь reverse, например.)
D>И дёргай его при каждом нажатии.

D>А глобальной коллекции не бывает — старую передаёшь, новую получаешь. Нет объектов с identity


Как тогда хранить list между вызовами callback-ов?
Я знаю, что нет identity. Но не предсталвяю, как вот в этом случае можно обойтись без модификации.

псевдоязык, инициализация главного окна

initWindow =
Window window
List list
window.onClick=onclick list

как функция obclick "будет возвращать модифицированный объект"? если ты скажешь, я буду очень удивлен. тут единственный вариант — дать на вход ей ссылку на mutable-список. Как хранить list между вызовами callback-ов?
Re[9]: haskell, изменяемое состояние
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 22.01.08 14:18
Оценка:
Здравствуйте, lse, Вы писали:

lse>Как тогда хранить list между вызовами callback-ов?


Хранить надо ссылку. Её то можно модифицировать (менять значение, на которое оно ссылается).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[10]: haskell, изменяемое состояние
От: lse  
Дата: 22.01.08 14:35
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Здравствуйте, lse, Вы писали:


lse>>Как тогда хранить list между вызовами callback-ов?


L>Хранить надо ссылку. Её то можно модифицировать (менять значение, на которое оно ссылается).


Ну а я о чем говорю уже 2 часа? Это-то и нужно было. Ссылка на объект — самое то. А тут говорят — ссылки запрещены.

Спасибо.
Re[11]: haskell, изменяемое состояние
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 22.01.08 14:56
Оценка:
Здравствуйте, lse, Вы писали:

lse>Ну а я о чем говорю уже 2 часа? Это-то и нужно было. Ссылка на объект — самое то. А тут говорят — ссылки запрещены.


Ты невнимательно читаешь — тебе говорили про ссылки с первых постов, запрещены модификации.

lse>Спасибо.


Рад, что смог помочь.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: haskell, изменяемое состояние
От: geniepro http://geniepro.livejournal.com/
Дата: 22.01.08 17:39
Оценка:
Здравствуйте, lse, Вы писали:

lse> Можно пример функции, на вход которой приходит список, а функция его модифицирует?


Ежели это список ссылок на мутабельные переменные (напр. IORef), то вот:
{- Алгоритм на псевдокоде примерно такой:

void sort (Ord el => el arr[])
{
    int len = length (arr);

    for (int i = 1; i < len; i++)
    {
        for (int j = 0; j < i; j++)
        {
            if (arr [j] > arr [i])
            {
                (arr [i], arr [j]) = (arr [j], arr [i]);
            }
        }
    }
}

-}

import Data.IORef
import Control.Monad

sort arr = do
    let len = length arr
    forM [1..len-1] $ \i -> do
        forM [0..i-1] $ \j -> do
            arr'i <- arr !!! i
            arr'j <- arr !!! j
            when (arr'j > arr'i) $ do
                 (arr !! i) =:= arr'j
                 (arr !! j) =:= arr'i

main = do
    array <- toIORefs [ 10, 9..1 ]

    putStr   "Unsorted array: "
    printArr array

    sort     array

    putStr   "Sorted array:   "
    printArr array


arr !!! n = readIORef $ arr !! n
ref =:= n = writeIORef ref n

fromIORefs   = mapM readIORef
toIORefs     = mapM newIORef
printArr arr = fromIORefs arr >>= print
Результат:
Unsorted array: [10,9,8,7,6,5,4,3,2,1]
Sorted array:   [1,2,3,4,5,6,7,8,9,10]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.