2014-02-20 5 views
3

Я строю код, чтобы получить понимание, на самом деле Solitaire solver. У меня есть простая реализация грубой силы, в которой используется государственная монада, на самом деле просто для того, чтобы доказать, что я могу ее использовать (она только подсчитывает количество вычислений каждого движения). Но теперь я хочу использовать Unboxed Mutable массивы для записи посещенных плат и, таким образом, ярлык оценки путей, когда я достигаю позиции доски, которая уже была посещена по другому пути. Кажется, что монашка ST не позволяет мне вступать в неявное состояние, но я должен использовать ST (или IO), чтобы получить доступ к массиву Mutable. Поэтому мне кажется, что я должен объединить два состояния Monads - State для потока состояния (на самом деле включающего Mutable array), а другой (ST) для получения функций Mutable array.Как я могу совместить монаду монахов и монадию штата (или эквивалент)?

  • Это право?
  • И если да, есть ли лучшая альтернатива, чем комбинация Data.Array.ST/Control.Monad.ST/Control.Monad.ST и mtl?
  • Если я иду по этому маршруту, имеет значение, какой заказ я собираю ST и State?
  • Должен ли я рассмотреть возможность прокатки собственной одиночной Монады на основе любого или обоих ST или состояний, чтобы избежать использования монадных трансформаторов?

ответ

5

Я не уверен на 100%, что ST-монада - это способ улучшить производительность для такой задачи поиска. Но предполагая, что это ... Вы можете «направить состояние», просто поставив состояние, которое хотите сохранить в STRef. Вы можете сделать это без необходимости комбинировать несколько монад вместе, что должно сделать вещи намного проще для вас.

Вам, безусловно, нужна монада ST или IO, если вы хотите изменить состояние. (Или монада STM, но это используется только для синхронизации потоков, которые вам здесь не нужны.)

Порядок, в котором уложены монады может вопрос - но в этом случае это не так. Если у вас было что-то вроде монады List и Monad Error, то в зависимости от порядка стекирования ошибка либо не удалась только одной возможности в списке, либо все возможностей в списке. Для вашего случая нет никаких эффектов, которые изменяются в зависимости от порядка стека.

... что повезло, так как нет трансформатора для превращения вещей в ST. Таким образом, ST имеет, чтобы быть внутренней монадой.

Сказав все это, опять же, я не думаю, что вам действительно нужен стек монады здесь. Я бы подумал, что это сделает простой STRef.

+0

Если я следую этому пути, как передать переменную состояния (которая включает в себя изменяемый массив)? Когда я прочитал ваше предложение, я бы создал STREF во главе моей рекурсивной функции и явно прочитал и написал его, убедившись, что STRef всегда отображается в функциях, определенных в функции верхнего уровня? В отличие от использования State, где это подразумевается, когда я использую monadic bind - могу ли я добиться того же самого, что и в ST? Если да, то как? – hdb3

+1

Вы можете определить 'type STState s st = ReaderT (STRef s st) (ST s)', а затем выполнить вычисления 'STState' с помощью' runSTState sts = newSTRef initState >> = runReaderT sts'. Этот подход изоморфен простому прохождению «STRef» вручную, но, возможно, более эстетично. Конечно, в этот момент вам может быть лучше, просто используя «StateT st (ST s)». –

+0

AFAIK, STM используется для _avoid_ любой синхронизации потоков. – user3974391

3

При использовании ST любых массивы или ссылки у вас есть на самом деле не состояния в смысле State монады слова: они никогда не изменяются! Вы можете думать о них как о указателе; указатель постоянный, хотя вещи, на которые он указывает, могут измениться. Поэтому вы можете просто передать свои массивы или ссылки или что-то еще в своих действиях ST как аргументы функции. Механизм StateT был бы уместным, если бы вы ожидали, что действие ST должно вернуть другой массив, чем тот, который был передан, т. Е. Не только изменить существующий массив, но и создать новый. Поскольку это вообще не так, StateT не подходит.

Если вы действительно хотите иметь блок трансформатора монады, вы можете разместить свои массивы и ссылки в среде монады ReaderT.Но это, вероятно, не нужно.

+0

Массив не будет «свежим» - возможно, обновляется в одном элементе, а старая версия больше не нужна. Я не понимаю, как ReaderT поможет, так как я хочу обновить состояние, когда я иду ... – hdb3

+0

@ hdb3 Я пытаюсь сказать, что вы ошибаетесь. Обновление одного элемента массива не создает новый массив - указатель один и тот же, только содержимое, лежащее за указателем, отличается! У вас нет какого-либо состояния для обновления. Все указатели остаются неизменными. –

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

  • Нет связанных вопросов^_^