这是来自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/Just
。 fail
让我向前推进,但我认为这不是解决方案。
在实践中,我可能错过了一个更重要的问题,并欢迎启蒙。
答案 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容器