我正在将一些Python代码转换为Haskell。业务逻辑相当复杂,我的Haskell代码越来越难看。
我的Python函数:
def f(some_state):
doAction1() # e.g. send_message("Hi there!")
if not userIsAuthenticated:
doAction2() # e.g. send_message("Please login")
return
if not userHasPermission:
doAction3() # e.g. send_message("Please sudo")
return
if somePredicate3:
doAction4()
if somePredicate4:
doAction5()
return
对于Haskell版本,我有两个约束:
tmp = []
,将所有操作附加到tmp
(不调用它们)并返回tmp
。然后,我会迭代列表来执行所有的操作(根本不是Pythonic!)。-
if a
then undefined
else if b
then undefined
else if c
then undefined
else if d
then undefined
else undefined
基本上,我想收集一个行动列表,并在必要时提前退出,这样我就可以写下如下内容:
tell Action1
when somePredicate1 $ tell doAction2
when somePredicate2 $ tell doAction3
...
tell
不是来自writer monad,而是一个函数(它不存在),它聚合了迄今为止“告诉”的所有内容(即writer monad),并在我退出时返回。
这真的感觉像是一个广义的非此即彼的单子,除了我需要保留在第一个左边之前发生的所有动作(不仅仅是左值),然后在第一个左边提前退出。我认为这个解决方案可能建立在MonadPlus或其他替代品的基础上,但我就是想不出什么好东西。基本上,一个花哨的守卫
。
也有可能我在过度工程中获得了太多的乐趣,我应该接受我的代码必须正确漂移。但那就不优雅了,不是吗?
编辑:为了清楚起见,我想要一个f::State类型的函数-
这听起来像是mtl控制下的投掷者的理想用法。蒙纳德。除了这样:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RecordWildCards #-}
module Main where
import Control.Monad.Except
data UnlockError =
UnlockErrorNoLogin
| UnlockErrorNeedsSudo
data State = State {
stateUserIsAuthenticated :: Bool
, stateUserHasPermission :: Bool
}
unlock :: MonadError UnlockError m => State -> m String
unlock State{..} = do
action1
unless stateUserIsAuthenticated
(throwError UnlockErrorNoLogin)
unless stateUserHasPermission
(throwError UnlockErrorNeedsSudo)
return "all"
where
action1 = return ()
main :: IO ()
main = do
state <- conjureState
case unlock state of
Left UnlockErrorNoLogin ->
p "please log in"
Left UnlockErrorNeedsSudo ->
p "please sudo"
Right count ->
p ("i love you with " ++ show count ++ " of my heart")
where
p =
putStrLn
conjureState =
return (State True True)
问题内容: 我正在为Android应用程序实现缓存机制。 我使用,就像发现的许多示例一样。问题是,当我向上或向下滚动时, 大多数 图像已被清除。我在LogCat中看到,每次应用程序加载新图像时,我的应用程序都会被垃圾回收。这意味着中的 大多数 不可见图像都消失了。 因此,每次我 滚动回到 较早的位置(之前我确实下载过图像)时,都必须再次下载图像-它们 不会被 缓存 。 我也研究了这个话题。根据Ma
有没有人尝试在多台计算机中并行启动Quartz作业应用程序? 我在我的应用程序中创建了Quartz集群作业,它在多台计算机中运行。石英工作良好,当我开始应用程序顺序,在所有主机一个接一个。然而,当我并行启动应用程序时,我会得到一些不同类型的错误。 例如: > 作业和触发器注册失败:null org.quartz.objectalreadyexistsexception:无法存储名称为“Trigge
我有两个问题。其中一个会把话题弄得乱七八糟:) 1)我遇到了一个问题,即无法找到关于不同垃圾收集器在Hotspot中如何工作的完整信息。但我不是在谈论垃圾收集器工作的一般描述(我们在互联网上有很多这样的信息),我是在谈论具体的算法。我找到了这本白皮书(Java HotSpot虚拟机中的内存管理)http://www.oracle.com/technetwork/Java/javase/tech/m
我们在几个应用程序节点上聚集了Quartz scheduler runner。应用程序节点需要更新,出于高可用性的原因,更新以滚动更新的方式进行。
以下代码 由IntelliJ转换为: 可以缩短为 这两个流版本不编译。 IntelliJ,暗示值中的i存在问题[i]: 不兼容的类型 必需:int找到:java。lang.对象 编译器抱怨: 错误:(35,17)java:接口java中的方法collect。util。流动IntStream不能应用于给定类型 必需:java。util。作用供应商,爪哇。util。作用ObjIntConsumer,j
在我们的kafka broker设置中,GC平均需要20毫秒,但随机增加到1-2秒。极端情况持续9秒。这种情况的发生频率相当随机。平均每天发生15次。我尝试过使用GCEasy,但没有给出任何见解。我的内存使用率为20%,但进程仍然使用交换,尽管内存可用。感谢您对如何将其最小化的任何意见 JVM选择: GC日志: