2013-02-22 2 views
2

Оригинальный вопрос

Последние версии Haskell (> 7.4.2?) Поставляются с пакетом mtl, который больше не предоставляет конструктор состояний как таковой, вместо этого предоставляет функцию состояния.Пример Haskell State в wikibooks: исправление за текущий Haskell?

Это путает примеры государства на странице Викиучебников здесь: http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

Может кто-то показать, как пересмотреть пример следующей статье «Введение в государство»? Это небольшие функции rollDie и rollDice.

На предыдущей странице есть блокнот рядом с заголовком «Определение государственной монады», в котором описывается вообще, что делать, но это слишком расплывчато для меня.

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

Спасибо!

Исходный код

------- Adding code for ghci01.hs------- 

-- http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State 
-- Introducing State heading and below 

import Control.Monad 
import System.Random 

type GeneratorState = State StdGen 

rollDie :: GeneratorState Int 
rollDie = do generator <- get 
      let (value, newGenerator) = randomR (1,6) generator 
      put newGenerator 
      return value 

-- Test rollDie 
-- evalState rollDie (mkStdGen 0) 

rollDice :: GeneratorState (Int, Int) 
rollDice = liftM2 (,) rollDie rollDie 

-- Test rollDice 
-- evalState rollDice (mkStdGen 666) 

------- In GHCi -------- 
ghci> :l dice01.hs 
[1 of 1] Compiling Main    (dice01.hs, interpreted) 
dice01.hs:7:23: Not in scope: type constructor or class `State' 
dice01.hs:10:27: Not in scope: `get' 
dice01.hs:12:14: Not in scope: `put' 
Failed, modules loaded: none. 

Добавление

Для тех, кто наткнуться здесь:

Основной темой этого вопроса вращается вокруг неработающего пример кода, и предупреждение в примечании на странице wikibooks, указанной выше. В этом поле указано, что для версии MTL> 2.0.0.0 часть кода примера не будет работать из-за изменения в Control.Monad.State.

В моем тесте участвовала платформа Haskell 2012.4.0.0, которая включает в себя GHC 7.4.2 и MTL, которые я с опозданием обнаружил как 1.1.1.1, на основе файла mtl.cabal. Таким образом, предупреждение Note не должно применяться, но, без сомнения, код примера не работает. Изменения, рекомендованные в ответах здесь (изменение импорта Control.Monad на Control.Monad.State), устранили проблему. Но очевидно, что это была проблема, связанная с некоторыми более ранними изменениями, а не с MTL 2.x, указанными в примечании.

С тех пор я смотрел источник для GHC 7.6.2, и там я вообще не нашел библиотеку MTL. Вместо этого файлы, связанные с государством, находятся в библиотеках/трансформаторах/Control/Monad/Trans/State. Затем я взял кучу запутанных обходов, в том числе проблему, что в настоящее время нет платформы Haskell, которая использует GHC позже, чем 7.4.2 (то есть: нет 7.6.2).

Тогда я нашел MTL документы (http://www.haskell.org/haskellwiki/Monad_Transformer_Library), которые указывают на этот StackOverflow Q & A: mtl, transformers, monads-fd, monadLib, and the paradox of choice ... что-то объясняет много, по крайней мере, 2-3 года назад.

+0

Я думаю, что эти функции работают с версией MTL версии 2.12 (текущий). Почему, по-вашему, они этого не делают? Можете ли вы опубликовать ошибку, которую вы получите, когда вы попробуете их (и ваш полный код)? –

+0

Я добавил код, который я пытался, который был скопирован, я думаю, дословно, со страницы wikibooks. Я вполне уверен, что это не ожидается, если я буду работать, в соответствии с указанным ящиком «Заметка», и сообщение об ошибке (отсутствующий конструктор или класс State) соответствует прогнозу Note. – gwideman

ответ

7

Код выше только одна проблема

Control.Monad ===> Control.Monad.State 

Единственное реальное время изменения кусает вас, когда у вас есть что-то вроде

foo :: State Int Int 
foo = State $ \a -> (a, a) -- This is an error 

но фиксируя это легко:

foo :: State Int Int 
foo = state $ \a -> (a, a) 

Конструктор типа State все еще существует, это просто конструктор данных был скрыт в пользу state. Это немного запутанно, потому что их обоих называют одинаковыми.

+0

Ах да, спасибо за ответ на вопрос как таковой, а также за дополнительное напоминание о различии между конструктором типа именованного типа и конструктором данных, многолетней ловушкой для неосторожных. [кашель]. – gwideman

+1

Я не уверен, что можно строго называть 'State' конструктором типа, это теперь псевдоним типа (' type State s = StateT s Identity'). –

+1

@ DanielFischer Это хороший момент, было бы более уместно ссылаться на него как на псевдоним типа? Хотя GHC не убирает псевдонимы типов довольно быстро? – jozefg

4

Код компилируется с использованием синонима типа State.Вам просто нужно

import Control.Monad.State 
+0

Спасибо за ваш ответ. Я не могу сказать, но я подозреваю, что вы были сначала за волосы, но я назначил отметку jozefg для использования ESP, чтобы определить, что я, вероятно, хотел узнать пару связанных фактов. Счастлив +1 ваш ответ. – gwideman

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