2014-10-18 7 views
0

Для назначения для FP нам необходимо написать функцию, которая выполняет монадическое вычисление состояния, заданное начальное состояние, а затем возвращает вычисленное значение и количество подсчитанных операций ,Невозможно сопоставить ожидаемый тип и застревать при назначении о государственных монадах

Графы выглядит следующим образом:

data Counts = Counts { 
    binds :: Int, 
    returns :: Int, 
    gets :: Int, 
    puts :: Int 
} deriving (Eq, Show) 

Где oneBind = Графы 1 0 0 0 (например). Был также установлен mempty и < *>, но я не смог использовать «mempty» вместо «Counts 0 0 0 0» с initCounts.

Государства определяются как:

newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) } 

До сих пор это то, что у меня есть, но я застрял на том же уровне в течение нескольких часов в настоящее время.

run :: State' s a -> s -> (a, Counts) 
run s ns = do 
    initState <- return ns 
    initCounts <- return (Counts 0 0 0 0) 
    newState <- return (runState' s (initState, initCounts)) 
    newCounts <- return (runState' (retCounts newState) (newState, initCounts)) 
    let st = let (a,_,_) = newState 
      in a 
    let count = let (c,_,_) = newCounts 
       in c 
    return (count) 


retCounts :: State' s a -> State' s Counts 
retCounts st = State' (\ (s, count) -> (calcCounts st, s, count)) 

calcCounts :: State' s a -> Counts 
calcCounts st = undefined 

Я предполагаю, что я должен использовать сопоставление с образцом в calcCounts, чтобы как-то на самом деле считать все операторы/функции, но сейчас я получаю ошибку соответствия типа:

Assignment4.hs:236:47: 
Couldn't match expected type ‘State' (a, s, Counts) a0’ 
      with actual type ‘(a, s, Counts)’ 
Relevant bindings include 
    newState :: (a, s, Counts) (bound at Assignment4.hs:235:5) 
    initState :: s (bound at Assignment4.hs:233:5) 
    ns :: s (bound at Assignment4.hs:232:7) 
    s :: State' s a (bound at Assignment4.hs:232:5) 
    run :: State' s a -> s -> (a, Counts) 
    (bound at Assignment4.hs:232:1) 
In the first argument of ‘retCounts’, namely ‘newState’ 
In the first argument of ‘runState'’, namely ‘(retCounts newState)’ 

Если бы я мог получить любая помощь в том, как я могу решить эту ошибку типа и некоторые намеки, чтобы идти отсюда, это было бы высоко оценено.

PS: Я понимаю, что это может быть хорошей идеей переименовать calcCounts к чему-то вроде calcFunctions

[EDIT: Я также получаю другую ошибку, когда я работаю вокруг этого один путем подачи фиктивное значение:

Assignment4.hs:233:5: 
No instance for (Monad ((,) a)) arising from a do statement 
In a stmt of a 'do' block: initState <- return ns 
In the expression: 
    do { initState <- return ns; 
     initCounts <- return (Counts 0 0 0 0); 
     newState <- return (runState' s (initState, initCounts)); 
     newCounts <- return (runState' retCounts (newState, initCounts)); 
     .... } 
In an equation for ‘run’: 
    run s ns 
     = do { initState <- return ns; 
      initCounts <- return (Counts 0 0 0 0); 
      newState <- return (runState' s (initState, initCounts)); 
      .... } 

]

ответ

0

Есть несколько проблем здесь.

There was also an mempty and <*> defined...

Возможно, вы имели в виду <> = mappend? <*> - оператор приложения для аппликативных функторов.

run :: State' s a -> s -> (a, Counts) 
run s ns = do 
    initState <- return ns 
    initCounts <- return (Counts 0 0 0 0) 
    newState <- return (runState' s (initState, initCounts)) 
    newCounts <- return (runState' (retCounts newState) (newState, initCounts)) 
    let st = let (a,_,_) = newState 
      in a 
    let count = let (c,_,_) = newCounts 
       in c 
    return (count) 

Во-первых, подумайте о том, какой тип вашего блока блокирован. Он имеет тот же тип, что и run s ns, который согласно вашему типу подписи для run равен (a, Counts). Как вы знаете, нотация работает только с монадами. (a, Counts) (или, точнее, ((,) a)) не является монадой, что является одной из причин, по которым GHC запутывается.

Далее, следует отметить, что в сделай блок:

initState <- return ns 

идентичен

let initState = ns 

Если переписать run, чтобы отразить это, мы получаем следующее:

run s ns = do 
    let initState = ns 
     initCounts = Counts 0 0 0 0 
     newState = runState' s (initState, initCounts) 
     newCounts = runState' (retCounts newState) (newState, initCounts) 
    let st = let (a,_,_) = newState 
      in a 
    let count = let (c,_,_) = newCounts 
       in c 
    return count 

Теперь мы можем увидеть следующую большую проблему: вы на самом деле не связываете монадические переменные i n ваш блок!Фактически, вручную используя newState и т. Д., Вы обходите всю точку государственной монады - отслеживать состояние для нас.

Дело в том, что все это не так сложно, как вы могли бы поверить; нам даже не нужно использовать обозначение. Я советую вам подумать об этом немного больше, прежде чем смотреть на текст ниже, чтобы узнать, сможете ли вы найти решение. В качестве подсказки: функция может быть написана просто в одной строке.


Вот как я мог бы написать run:

run :: State' s a -> s -> (a, Counts) 
run s ns = let (a, _, counts) = runState' s (ns, Counts 0 0 0 0) in (a, counts) 
+0

Большое спасибо за объяснения моих ошибок. Наше задание состояло из 12 меньших задач, из которых все они (за исключением этого, по-видимому,) получили Monad «что-то», так что, должно быть, это меня сбивало с толку. Это действительно помогает мне понять это лучше. Я чувствовал себя очень глупо, когда понял, что код мог быть написан так компактно. Не могу поверить, что я потратил столько времени на это ха-ха! –

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

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