使用另一个函数

时间:2016-05-15 09:55:18

标签: haskell template-haskell

它只是程序的骨架。我有主要功能,

State [Dec] [Dec]
mainCon = do
  acc <- get
  put []
  modify $ (++) [some func]
  return acc

在一个阶段我调用函数:

foldlWithKey'
                         (\list' key' val' ->
    if (...)
          then
                (Control.Monad.State.modify $ (Prelude.++) [elem]) >>
                some code
                : list')
          else
                (Control.Monad.State.modify $ (Prelude.++) []) >>
                some code
                : list')
                             )
                             []
                             (map')

并希望在mainCon中修改State,但继续遍历map'。错误是:

No instance for (MonadState [Dec] [])
      arising from a use of ‘Control.Monad.State.modify’
    In the expression: Control.Monad.State.modify
来自Template Haskell的

[Dec]。我怎样才能简单地解决这个问题?

1 个答案:

答案 0 :(得分:1)

从概念上讲,问题在于 传递给foldWithKey'的第一个参数必须是纯函数, 但是当你使用modify时,你正在创建一个有状态的计算, 不是一个纯粹的功能。

显然你正试图迭代一个hashmap 在遍历期间保持某种状态。 foldWithKey' 已经给你那个状态 - 它是第一个参数 积累功能:

                  v-- current state
foldlWithKey' :: (a -> k -> v -> a) -> a -> HashMap k v -> a
                     new state --^     ^-- initial         ^-- final
                                           state               state

累积功能采用当前状态,键和值 并返回更新的状态。然后,如果你给foldWithKey'一个首字母 说它将返回最终状态。

以下是使用与foldWithKey相同的示例 foldWithKey'除了参数略有不同之外 不同的顺序。

函数evenOdds返回两个列表 - 一个包含 具有偶数值的键和具有奇数值的键。

状态是对(even,odds)和累积函数go 根据当前键和值返回更新后的状态。

 {-# LANGUAGE NoMonomorphismRestriction #-}

 import qualified Data.HashMap as H

 myMap = H.fromList [ ("a",1), ("b",2), ("c",3), ("d",4) ]

 evenOdds :: ([String],[String])
 evenOdds = H.foldWithKey go ([],[]) myMap
   where  go :: String -> Int -> ([String],[String]) -> ([String],[String])
          go k a (evens,odds) = 
             if even a then ( evens ++ [k], odds)
                       else ( evens       , odds ++ [k] )