- 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/
可以抛出异常的函数可以有[pure]属性吗? 最佳答案 根据 https://msdn.microsoft.com/en-us/library/system.diagnostics.contracts
我使用的是纯 css 推送导航。它工作得很好,但是我不知道如何在单击导航链接时隐藏菜单。您必须手动单击菜单图标才能使菜单返回隐藏状态。但是,当单击链接并且站点跳转到某个部分时,我希望菜单自动滑入隐藏状
我正在尝试让纯 CSS 下拉菜单正常工作。它在很大程度上确实有效,除了其他内容似乎显示出来但我不知道为什么。 http://jsfiddle.net/uQveP/4/ 有人可以告诉我我做错了什么吗?
这个问题在这里已经有了答案: What is a "callback" in C and how are they implemented? (9 个回答) 关闭 8 年前。 我正在以这种方式实现回
我想在不使用 Javascript 或任何其他语言的情况下,使用 HTML 和 CSS 创建一个 Page Back Button。我想用纯 HTML 和 CSS 来完成。 我进行了搜索,但每次代码中
我对序言很陌生。据我所知,Pure Prolog 仅限于 Horn 子句。 这是一个非常简单的序言程序 - % student( Snr , FirstName , LastName ,
我想在加载数据时对容器使用以下加载指示器。 问题是, slider 具有固定的宽度和高度(300 像素和 300 像素),但我希望它能够动态适应容器。当我尝试添加宽度时:140px;和高度:140px
当内容超过可用宽度时,我需要启用滚动阴影。这是我试图用纯 css(没有 JS)来实现的。我遇到了很多文章,可以使用 css 多背景和背景附件来实现。如果内容是文本类型,则可以使用下面的 jsfilld
我正在编写一个上古卷轴在线插件,它由一个名为 Havok Script 的轻微修改的 Lua 5.1 引擎支持。 .这个Lua环境不允许访问os , io , package , debug模块或任何
我自己尝试过将 Arduino 库编译成他们自己的独立库并链接到 Eclipse 中的一个项目,但在此过程中遇到了一些问题。 是否有关于如何启动和运行的体面指南?我一直很难在网上找到一个真正有效的..
我在这里遇到了一些麻烦。我正在尝试使用本地存储创建一个待办事项列表,但我唯一要做的就是将列表项添加到本地存储并删除 所有项目 从本地存储中删除,但我无法从列表中删除单个 SELECTED 项目。有人可
我的问题很简单。考虑以下 CodePen .是否有可能仅使用 css 就可以获得相同的结果?换句话说,如果不使用 javascrip 如何做到这一点?非常感谢! Nachos are
我正在使用没有 jquery 的 angularjs,并尝试创建滚动事件监听器。 尝试过这种方法: $rootScope.$watch(function() { return $windo
我正在尝试使用纯 webgl 创建虚线。我知道这已经有一个问题,也许我很笨,但我不知道如何让它发挥作用。我理解这个概念,但我不知道如何在着色器中获取沿路径的距离。以前的答案有以下行: varying
我正在尝试用纯 JavaScript 制作工具提示,显示在 hover .就像 Stack Overflow 中将鼠标悬停在配置文件名称上的一个 div显示。 我尝试使用 onmouseover ,
我想要通过 AJAX 将监听器添加到新元素的想法: 例如,现在我有 hello world 我为每个 添加了一个监听器,但是当我通过 AJAX 加载新元素时,它没有监听器;我不完全确定问题是什么。
如果我错误地提出了这个问题,或者之前已经有人问过并回答过这个问题,我提前表示歉意。我的搜索发现了类似的基于 JQuery 和/或静态日期的问答,我正在寻找具有动态日期的纯 JavaScript 解决方
在 Real World Haskell, Chapter 28, Software transactional memory ,开发了一个并发的网络链接检查器。它获取网页中的所有链接,并使用 HEA
我正在尝试取消 jQuery-fy 一个聪明的 piece of code ,但有点太聪明了。 目标是simple 。将图像从桌面拖动到浏览器。 在这次 unjQueryfication 过程中,我发
如何重新创建 jQuery end() $('#id') .find('.class') .css('font',f) .end() .find('.seven') .css(b,'red') 我有什
我是一名优秀的程序员,十分优秀!