- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
具体来说,假设我有这个 monadT 堆栈:
type MHeap e ret = MaybeT ( StateT [e] Identity ) ret
runMheap :: MHeap e ret -> [e] -> ( Maybe ret, [e] )
runMheap m es = runIdentity $ runStateT ( runMaybeT m ) es
MHeap
查找列表的第 i 个元素(请注意,我们可能会在此处出现越界错误),然后如果该元素存在,则将其附加到列表的末尾,否则保持列表不变。在代码中:
mheapOp' :: Int -> MHeap Int ( Maybe Int )
mheapOp' i = do
xs <- lift $ get
-- I would like to use the pure function ( !! ) here
let ma = fndAtIdx i xs
-- I would also like to get rid these case statements
-- Also how do you describe 'no action' on the list?
case ma of
Nothing -> lift $ modify ( ++ [] )
Just a -> lift $ modify ( ++ [a] )
return ma
-- Since I dont know how to use the pure function above, I'm using this hack below
fndAtIdx i xs = if length xs > i then Just $ xs !! i else Nothing
case 1: runMheap(mheapOp' 1 ) [1..3] // (Just (Just 2),[1,2,3,2])
case 2: runMheap(mheapOp' 10 ) [1..3] // (Just Nothing,[1,2,3])
( Just 2, [1,2,3,2] ) and ( Nothing, [1,2,3] )
最佳答案
我建议您坚持使用 findAtIdx
,返回 Nothing
, 而不是使用像 (!!)
这样的偏函数使用 error
.您实际需要的是以下类型的函数:
hoistMaybe :: (Monad m) => Maybe a -> MaybeT m a
findAtIdx
命令在周围正确
MaybeT
像这样的单子(monad):
mheapOp' :: Int -> MHeap Int Int
mheapOp' i = do
xs <- lift get
-- if 'findAtIdx' is 'Nothing', it will stop here and not call 'modify'
a <- hoistMaybe (findAtIdx i xs)
lift $ modify (++ [a])
return a
hoistMaybe ma = MaybeT (return ma)
errors
图书馆(完全披露:我写的)。请注意,此库还重新导出
atMay
来自
safe
的函数你的图书馆,就像你的
findAtIdx
功能。
hoistMaybe
是一个“单子(monad)态射”,这意味着它应该满足以下定律:
-- It preserves empty actions, meaning it doesn't have any accidental complexity
hoistMaybe (return x) = return x
-- It distributes over 'do' blocks
hoistMaybe $ do x <- m = do x <- hoistMaybe m
f x hoistMaybe (f x)
hoistMaybe (return x)
-- Definition of 'return' in the 'Maybe' monad:
= hoistMaybe (Just x)
-- Definition of 'hoistMaybe'
= MaybeT (return (Just x))
-- Definition of 'return' in the 'MaybeT' monad
= return x
hoistMaybe $ do x <- m
f x
-- Definition of (>>=) in the 'Maybe' monad:
= hoistMaybe $ case m of
Nothing -> Nothing
Just a -> f a
-- Definition of 'hoistMaybe'
= MaybeT $ return $ case m of
Nothing -> Nothing
Just a -> f a
-- Distribute the 'return' over both case branches
= MaybeT $ case m of
Nothing -> return Nothing
Just a -> return (f a)
-- Apply first monad law in reverse
= MaybeT $ do
x <- return m
case x of
Nothing -> return Nothing
Just a -> return (f a)
-- runMaybeT (MaybeT x) = x
= MaybeT $ do
x <- runMaybeT (MaybeT (return m))
case x of
Nothing -> return Nothing
Just a -> runMaybeT (MaybeT (return (f a)))
-- Definition of (>>=) for 'MaybeT m' monad in reverse
= do x <- MaybeT (return m)
MaybeT (return (f x))
-- Definition of 'hoistMaybe' in reverse
= do x <- hoistMaybe m
hoistMaybe (f x)
mheapOp
内联:
import Control.Monad
import Control.Error
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.State
import Data.Functor.Identity
-- (State s) is the exact same thing as (StateT s Identity):
-- type State s = StateT s Identity
type MHeap e r = MaybeT (State [e]) r
mheapOp :: Int -> MHeap Int Int
{-
mheapOp i = do
xs <- lift get
a <- hoistMaybe (atMay xs i)
lift $ modify (++ [a])
return a
-- Inline 'return' and 'lift' for 'MaybeT', and also inline 'hoistMaybe'
mheapOp i = do
xs <- MaybeT $ liftM Just get
a <- MaybeT $ return $ atMay xs i
MaybeT $ liftM Just $ modify (++ [a])
MaybeT $ return $ Just a
-- Desugar 'do' notation
mheapOp i =
(MaybeT $ liftM Just get) >>= \xs ->
(MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- Inline first '(>>=)' (which uses 'MaybeT' monad)
mheapOp i =
MaybeT $ do
mxs <- runMaybeT (MaybeT $ liftM Just get)
case mxs of
Nothing -> return Nothing
Just xs -> runMaybeT $
(MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- runMaybeT (MaybeT x) = x
mheapOp i =
MaybeT $ do
mxs <- liftM Just get
case mxs of
Nothing -> return Nothing
Just xs -> runMaybeT $
(MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- Inline definition of 'liftM'
mheapOp i =
MaybeT $ do
mxs <- do xs' <- get
return (Just xs')
case mxs of
Nothing -> return Nothing
Just xs -> runMaybeT $
(MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
{- Use third monad law (a.k.a. the "associativity law") to inline the inner do
block -}
mheapOp i =
MaybeT $ do
xs <- get
mxs <- return (Just xs)
case mxs of
Nothing -> return Nothing
Just xs -> runMaybeT $
(MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
{- Use first monad law (a.k.a. the "left identity law"), which says that:
x <- return y
... is the same thing as:
let x = y
-}
mheapOp i =
MaybeT $ do
xs' <- get
let mxs = Just xs'
case mxs of
Nothing -> return Nothing
Just xs -> runMaybeT $
(MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- Inline definition of 'mxs'
mheapOp i =
MaybeT $ do
xs' <- get
case (Just xs') of
Nothing -> return Nothing
Just xs -> runMaybeT $
(MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
{- The 'case' statement takes the second branch, binding xs' to xs.
However, I choose to rename xs' to xs for convenience, rather than rename xs
to xs'. -}
mheapOp i =
MaybeT $ do
xs <- get
runMaybeT $ (MaybeT $ return $ atMay xs i) >>= \a ->
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- Inline the next '(>>=)'
mheapOp i =
MaybeT $ do
xs <- get
runMaybeT $ MaybeT $ do
ma <- runMaybeT $ MaybeT $ return $ atMay xs i
case ma of
Nothing -> return Nothing
Just a -> runMaybeT $
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- runMaybeT (MaybeT x) = x
mheapOp i =
MaybeT $ do
xs <- get
do ma <- return $ atMay xs i
case ma of
Nothing -> return Nothing
Just a -> runMaybeT $
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- You can inline the inner 'do' block because it desugars to the same thing
mheapOp i =
MaybeT $ do
xs <- get
ma <- return $ atMay xs i
case ma of
Nothing -> return Nothing
Just a -> runMaybeT $
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- Use first monad law
mheapOp i =
MaybeT $ do
xs <- get
let ma = atMay xs i
case ma of
Nothing -> return Nothing
Just a -> runMaybeT $
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- Inline definition of 'ma'
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> runMaybeT $
(MaybeT $ liftM Just $ modify (++ [a])) >>= \_ ->
(MaybeT $ return $ Just a)
-- Inline the next '(>>=)'
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> runMaybeT $ MaybeT $ do
mv <- runMaybeT $ MaybeT $ liftM Just $ modify (++ [a])
case mv of
Nothing -> return Nothing
Just _ -> runMaybeT $ MaybeT $ return $ Just a
-- runMaybeT (MaybeT x) = x
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> do
mv <- liftM Just $ modify (++ [a])
case mv of
Nothing -> return Nothing
Just _ -> return (Just a)
-- Inline definition of 'liftM'
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> do
mv <- do x <- modify (++ [a])
return (Just x)
case mv of
Nothing -> return Nothing
Just _ -> return (Just a)
-- Inline inner 'do' block using third monad law
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> do
x <- modify (++ [a])
mv <- return (Just x)
case mv of
Nothing -> return Nothing
Just _ -> return (Just a)
-- Use first monad law to turn 'return' into 'let'
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> do
x <- modify (++ [a])
let mv = Just x
case mv of
Nothing -> return Nothing
Just _ -> return (Just a)
-- Inline definition of 'mv'
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> do
x <- modify (++ [a])
case (Just x) of
Nothing -> return Nothing
Just _ -> return (Just a)
-- case takes the 'Just' branch, binding 'x' to '_', which goes unused
mheapOp i =
MaybeT $ do
xs <- get
case (atMay xs i) of
Nothing -> return Nothing
Just a -> do
modify (++ [a])
return (Just a)
{- At this point we've completely inlined the outer 'MaybeT' monad, converting
it to a 'StateT' monad internally. Before I inline the 'StateT' monad, I
want to point out that if 'atMay' returns 'Nothing', the computation short
circuits and doesn't call 'modify'.
The next step is to inline the definitions of 'return, 'get', and 'modify':
-}
mheapOp i =
MaybeT $ do
xs <- StateT (\as -> return (as, as))
case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a -> do
StateT (\as -> return ((), as ++ [a]))
StateT (\as -> return (Just a , as))
-- Now desugar both 'do' blocks:
mheapOp i =
MaybeT $
StateT (\as -> return (as, as)) >>= \xs ->
case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a ->
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as))
-- Inline first '(>>=)', which uses 'StateT' monad instance
mheapOp i =
MaybeT $ StateT $ \as0 -> do
(xs, as1) <- runStateT (StateT (\as -> return (as, as))) as0
runStateT (case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a ->
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) as1
-- ^
-- Play close attention to this s1 |
-- runStateT (StateT x) = x
mheapOp i =
MaybeT $ StateT $ \as0 -> do
(xs, as1) <- (\as -> return (as, as)) as0
runStateT (case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a ->
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) as1
-- Apply (\as -> ...) to as0, binding 'as0' to 'as'
mheapOp i =
MaybeT $ StateT $ \as0 -> do
(xs, as1) <- return (as0, as0)
runStateT (case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a ->
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) as1
-- Use first monad law to convert 'return' to 'let'
mheapOp i =
MaybeT $ StateT $ \as0 -> do
let (xs, as1) = (as0, as0)
runStateT (case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a ->
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) as1
{- The let binding says that xs = as0 and as1 = as0, so I will rename all of
them to 'xs' since they are all equal -}
mheapOp i =
MaybeT $ StateT $ \xs -> do
runStateT (case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a ->
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) xs
-- do m = m, so we can just get rid of the 'do'
mheapOp i =
MaybeT $ StateT $ \xs ->
runStateT (case (atMay xs i) of
Nothing -> StateT (\as -> return (Nothing, as))
Just a ->
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) xs
-- Distribute the 'runStateT ... xs' over both 'case' branches
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> runStateT (StateT (\as -> return (Nothing, as))) xs
Just a -> runStateT (
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) xs
-- runStateT (StateT x) = x
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> (\as -> return (Nothing, as)) xs
Just a -> runStateT (
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) xs
-- Apply (\as -> ...) to 'xs', binding 'xs' to 'as'
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> runStateT (
StateT (\as -> return ((), as ++ [a])) >>= \_ ->
StateT (\as -> return (Just a , as)) ) xs
-- Inline the '(>>=)'
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> runStateT (StateT $ \as0 -> do
(_, as1) <- runStateT (StateT (\as -> return ((), as ++ [a]))) as0
runStateT (StateT (\as -> return (Just a , as))) as1 ) xs
-- runStateT (StateT x) = x
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> (\as0 -> do
(_, as1) <- (\as -> return ((), as ++ [a])) as0
(\as -> return (Just a , as)) as1 ) xs
-- Apply all the functions to their arguments
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> (\as0 -> do
(_, as1) <- return ((), as0 ++ [a])
return (Just a , as1) ) xs
-- Use first monad law to convert 'return' to 'let'
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> (\as0 -> do
let (_, as1) = ((), as0 ++ [a])
return (Just a , as1) ) xs
-- Let binding says that as1 = as0 ++ [a], so we can inline its definition
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> (\as0 -> do
return (Just a , as0 ++ [a]) ) xs
-- do m = m
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> (\as0 -> return (Just a , as0 ++ [a])) xs
-- Apply (\as0 -> ...) to 'xs', binding 'xs' to 'as0'
mheapOp i =
MaybeT $ StateT $ \xs ->
case (atMay xs i) of
Nothing -> return (Nothing, xs)
Just a -> return (Just a , xs ++ [a])
-- Factor out the 'return' from the 'case' branches, and tidy up the code
mheapOp i =
MaybeT $ StateT $ \xs ->
return $ case (atMay xs i) of
Nothing -> (Nothing, xs)
Just a -> (Just a , xs ++ [a])
-}
-- One last step: that last 'return' is for the 'Identity' monad, defined as:
mheapOp i =
MaybeT $ StateT $ \xs ->
Identity $ case (atMay xs i) of
Nothing -> (Nothing, xs)
Just a -> (Just a , xs ++ [a])
{- So now we can clearly say what the function does:
* It takes an initial state named 'xs'
* It calls 'atMay xs i' to try to find the 'i'th value of 'xs'
* If 'atMay' returns 'Nothing, then our stateful function returns 'Nothing'
and our original state, 'xs'
* If 'atMay' return 'Just a', then our stateful function returns 'Just a'
and a new state whose value is 'xs ++ [a]'
Let's also walk through the types of each layer:
layer1 :: [a] -> Identity (Maybe a, [a])
layer1 = \xs ->
Identity $ case (atMay xs i) of
Nothing -> (Nothing, xs)
Just a -> (Just a, xs ++ [a])
layer2 :: StateT [a] Identity (Maybe a)
-- i.e. State [a] (Maybe a)
layer2 = StateT layer1
layer3 :: MaybeT (State [a]) a
layer3 = MaybeT layer2
-}
关于haskell - 在 MaybeT ( StateT ) monadT 堆栈中调用纯函数以使错误传播的惯用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15724810/
我已经使用 vue-cli 两个星期了,直到今天一切正常。我在本地建立这个项目。 https://drive.google.com/open?id=0BwGw1zyyKjW7S3RYWXRaX24tQ
您好,我正在尝试使用 python 库 pytesseract 从图像中提取文本。请找到代码: from PIL import Image from pytesseract import image_
我的错误 /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference
我已经训练了一个模型,我正在尝试使用 predict函数但它返回以下错误。 Error in contrasts<-(*tmp*, value = contr.funs[1 + isOF[nn]])
根据Microsoft DataConnectors的信息我想通过 this ODBC driver 创建一个从 PowerBi 到 PostgreSQL 的连接器使用直接查询。我重用了 Micros
我已经为 SoundManagement 创建了一个包,其中有一个扩展 MediaPlayer 的类。我希望全局控制这个变量。这是我的代码: package soundmanagement; impo
我在Heroku上部署了一个应用程序。我正在使用免费服务。 我经常收到以下错误消息。 PG::Error: ERROR: out of memory 如果刷新浏览器,就可以了。但是随后,它又随机发生
我正在运行 LAMP 服务器,这个 .htaccess 给我一个 500 错误。其作用是过滤关键字并重定向到相应的域名。 Options +FollowSymLinks RewriteEngine
我有两个驱动器 A 和 B。使用 python 脚本,我在“A”驱动器中创建一些文件,并运行 powerscript,该脚本以 1 秒的间隔将驱动器 A 中的所有文件复制到驱动器 B。 我在 powe
下面的函数一直返回这个错误信息。我认为可能是 double_precision 字段类型导致了这种情况,我尝试使用 CAST,但要么不是这样,要么我没有做对...帮助? 这是错误: ERROR: i
这个问题已经有答案了: Syntax error due to using a reserved word as a table or column name in MySQL (1 个回答) 已关闭
我的数据库有这个小问题。 我创建了一个表“articoli”,其中包含商品的品牌、型号和价格。 每篇文章都由一个 id (ID_ARTICOLO)` 定义,它是一个自动递增字段。 好吧,现在当我尝试插
我是新来的。我目前正在 DeVry 在线学习中级 C++ 编程。我们正在使用 C++ Primer Plus 这本书,到目前为止我一直做得很好。我的老师最近向我们扔了一个曲线球。我目前的任务是这样的:
这个问题在这里已经有了答案: What is an undefined reference/unresolved external symbol error and how do I fix it?
我的网站中有一段代码有问题;此错误仅发生在 Internet Explorer 7 中。 我没有在这里发布我所有的 HTML/CSS 标记,而是发布了网站的一个版本 here . 如您所见,我在列中有
如果尝试在 USB 设备上构建 node.js 应用程序时在我的树莓派上使用 npm 时遇到一些问题。 package.json 看起来像这样: { "name" : "node-todo",
在 Python 中,您有 None单例,在某些情况下表现得很奇怪: >>> a = None >>> type(a) >>> isinstance(a,None) Traceback (most
这是我的 build.gradle (Module:app) 文件: apply plugin: 'com.android.application' android { compileSdkV
我是 android 的新手,我的项目刚才编译和运行正常,但在我尝试实现抽屉导航后,它给了我这个错误 FAILURE: Build failed with an exception. What wen
谁能解释一下?我想我正在做一些非常愚蠢的事情,并且急切地等待着启蒙。 我得到这个输出: phpversion() == 7.2.25-1+0~20191128.32+debian8~1.gbp108
我是一名优秀的程序员,十分优秀!