2013-11-14 3 views
2

Я довольно новичок в Haskell, поэтому любая помощь приветствуется!Haskell Mutable Structure with Immutable Shell

Я использую IOArray для обновления случайных элементов в постоянном пространстве. У меня есть оболочка, которая выглядит следующим образом:

data W = W{ arr:: IO (IOArray Int Node), n :: Int, ... }

Однако, я не могу найти способ, чтобы обновить arr так, что это видно, когда обертку передается вокруг, не делая что-то вроде wrappper{arr = x}, который тратит впустую много времени GC. В тестах это оказывается слишком медленным.

Есть ли способ обновить arr, чтобы он был глобально видимым? Благодаря!

+3

Переменные данные в Haskell должны быть обернуты в Монаду, возможно, посмотрите, не подходит ли монашка 'ST' для ваших нужд. – jozefg

+3

jozefg прав: есть также' STArray', и обратите внимание, что 'runST' может превратить действие 'ST' в чистое значение. –

+0

'данные W s = W {arr :: STArray s Int Node, ...}'. Должен ли я просто создать массив целиком, прежде чем поместить его в оболочку? Это может быть жизнеспособным способом сделать это – Craig

ответ

3

Вот краткий пример того, как использовать ST массивы

import Data.Array.ST hiding (unsafeThaw) -- Deprecated 
import Data.Array (Array) 
import Data.Array.Unsafe (unsafeThaw) -- If you really really really need it 

newtype W a = W {arr :: Array Integer a} 

modifyW :: a -> W a -> W a 
modifyW v (W arr) = W $ runSTArray $ do -- The double $ is on purpose, . doesn't 
             -- play so well with Rank n types. 
    a <- thaw arr -- Turn `arr` into something we can modify 
    writeArray a 1 v -- modify it 
    return a 

Это обеспечит вычисление чистое, но массив не будет скопирован в modifyW, все эти изменения являются постоянным временем. Если вы не можете себе позволить какое-либо копирование, вы можете использовать unsafeThaw. Но это хорошо .. небезопасно. Он действительно изменит чистый массив, поэтому вам нужно быть предельно осторожным, чтобы не пытаться использовать чистую структуру после запуска modifyW. Это намного сложнее, чем кажется, благодаря ленивой оценке, поэтому я предупреждаю вас об этом.

С этим стилем, считываемый из чистого Array, тогда, когда вам нужно изменить его, вы бежите в ST монады, которая позволяет вам делать нечистые вещи, но не даст им просачиваться в остальной части вашей программы.

+0

Это потрясающе! Я постараюсь изо всех сил избегать этих небезопасных функций в будущем, но они, безусловно, хороший способ сойти с ног! – Craig

+0

@Craig Не заходите за борт :) Обычно, когда вы оказываетесь в поисках «небезопасного», вы делаете что-то неправильно. Но да, иногда они бесценны – jozefg

+1

@Craig ", но они, безусловно, хороший способ сбиться с земли!" Я бы хотел дать более сильный «нет»! ответ на это; Я думаю, что «небезопасные» функции следует рассматривать как (опасно) доступный интерфейс плагина к внутренним компонентам GHC. Привязка динамита к вашим ботинкам также является хорошим способом выйти из-под земли :) – jberryman

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