状态变换器:在(可能是Bool)中无需任何东西

时间:2015-01-15 15:40:52

标签: haskell

这是来自nicta课程(因此List = [], Optional = Maybe, ...),所以我不是在寻找一个完整的解决方案,但我仍然坚持使用状态变换器问题。目的是从列表中过滤重复项,如果传递任何数字则完全失败> 100。

-- filtering :: Applicative f => (a -> f Bool) -> List a -> f (List a)

distinctF :: (Ord a, Num a) => List a -> Optional (List a)
distinctF lst = case runStateT (filtering go lst) S.empty of
  Full (val, _) -> Full val
  Empty         -> Empty
  where
    --go :: a -> StateT (S.Set a) Optional Bool
    go x = do
      s <- getT
      if x > 100 then do
        return *?*Empty / False*?*

go = undefined期间进行了这次类型检查,但我很难将Empty放入return包裹,例如False中的Full/Justfail让我向前推进,但我认为这不是解决方案。

在实践中,我可能错过了一个更重要的问题,并欢迎启蒙。

2 个答案:

答案 0 :(得分:1)

如果目标是编写功能同时进行:独特过滤和同时对大输入失败,那么你的骨架非常正确:

distinctF :: (Ord a, Num a) => List a -> Optional (List a)
distinctF lst = evalStateT (go lst) S.empty -- evalStateT is your case runStateT part
  where -- on empty input we just return empty list
        go []     = return []
        -- otherwise
        go (x:xs)
          -- we check whether we should 'fail'
          -- for that we *lift* the value from underlying monad (Optional) into our StateT Optional
          | x > 100   = lift $ Empty
          | otherwise = do
            -- the stuff to do
            -- get the state, do nothing if x is in there
            -- otherwise add x to the state and recurse

因此,对于您的问题,您需要lift Empty,而不是return

答案 1 :(得分:0)

好的,所以我终于找到了一种方法,意识到我可以构建精确正确的返回类型,而不是试图依赖return

  go x = do
    if x > 100 then
      StateT (\_ -> Empty)          -- `return` a fail
    else do
      st <- getT

但是,我仍然不太确定<-如何打开StateT和内部monadic容器