我正在尝试将 MonadError 与 Parsec 一起使用。我想出了以下代码片段:
f5 = do
    char 'a'
    throwError "SomeError"
f6 = f5 `catchError` (\e -> unexpected $ "Got the error: " ++ e)
ret = runErrorT (runParserT f6 () "stdin" "a")
但是,retis Left "SomeError",似乎 catchError 没有任何效果。在这里使用 MonadError 的正确方法是什么?
我更喜欢使用 MonadError 而不是 Parsec 自己的错误处理,例如当我有:
try (many1 parser1) <|> parser2
如果 parser1 在这里失败, parser2 将继续,但我希望有一个完全中止解析的例外。
我在程序的不同级别有两个类型的控件结构声明.最下面的是Agent一个StateT有IO能力的.第二个是StateT具有Agent功能的另一个,第三个是(Plan)是一个ErrorT.
type Agent = StateT AgentState IO
type Plan = ErrorT PlanError (StateT PlanState Agent)
评估a的最佳方法是Plan什么?我写了下面的代码,但它不是很少,因为有大量的嵌套runStateT和runErrorT调用.
foo :: Plan ()
defaultAgentState :: AgentState
runStateT (runStateT (runErrorT foo) (PlanState 0)) defaultAgentState
有更简单/更好的东西吗?
我正在尝试使用任务并行库对树进行求和,其中只生成子任务,直到遍历树直到某个深度,否则它使用延续传递样式对剩余的子节点求和,以避免堆栈溢出.
但是,代码看起来很丑陋 - 使用状态monad来承载当前深度会很好,但状态monad不是尾递归.或者,我如何修改继续monad来携带状态?或者创建状态和延续monad的组合?
let sumTreeParallelDepthCont tree cont = 
  let rec sumRec tree depth cont =
    let newDepth = depth - 1
    match tree with
    | Leaf(num) -> cont num
    | Branch(left, right) ->
      if depth <= 0 then
        sumTreeContMonad left (fun leftM ->
          sumTreeContMonad right (fun rightM ->
            cont (leftM + rightM )))
      else 
        let leftTask = Task.Factory.StartNew(fun () -> 
              let leftResult = ref 0
              sumRec left newDepth (fun leftM -> 
                leftResult := leftM)
              !leftResult
              )
        let rightTask = …我正在研究monad变形金刚,我读了这篇关于如何避免lifts的帖子.
我的想法是,MonadIO有单子在其中IO可以嵌入,并MonadWriter w有单子在其中WriterT w可以嵌入.所以我编写了下面的代码(读取,累积和记录数字,直到我们得到零),其中使用explicit的工作版本lift在注释中.但GHC抱怨道.我究竟做错了什么?
{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.IO.Class
import Control.Monad.Writer.Class (MonadWriter)
import Control.Monad.Trans.Reader
import Control.Monad.Trans.Writer
-- f :: ReaderT Int (WriterT [String] IO) Int
-- m1 = ReaderT, m2 = WriterT
f :: (MonadWriter [String] m1, MonadIO m2) => m1 (m2 (IO Int))
f = do
    s <- liftIO getLine
    tell ["Input: " ++ s] -- lift $ tell ["Input: " ++ s]
    let …由于变压器的嵌套:: T2 of T1 of M0,我该怎么利用:: T2 of M0,:: M2?
这是一个例子:我正在编写一些需要读取,记录和状态的函数.定义:
gameRoutine :: WriterT [String] (ReaderT Env (State Viable)) NUM
如果我想打个电话
 stateFunction :: State Viable NUM
甚至stateWithReaderFunction :: ReaderT Env (State Viable) NUM,
我可以用lift:
gameRoutine = do
    x <- lift . lift $ stateFunction
    y <- lift $ stateWithReaderFunction
但是我怎么打电话writerFunction :: Writer [String] a?
我writerStateFunction :: WriterT [String] (State Viable) NUM该如何调用(gameRoutine定义之间的区别是ReaderT缺少图层)?
显然,我不想将他们的定义提升为其中之一 …
嗨,我正在寻找一种允许monad堆栈跳过剩余动作的好方法,而不会完全跳过.有点像returnC系列语言.
例如,假设我正在使用monadic动作来产生副作用
type MyMonad = ??
doStuff :: MyMonad ()
doStuff = do
   r <- doSomething
   -- equivalent to if (r == "X") return; in C
   dontGoPastHereIf (r == "X")
   doSomeSideEffects r
所以我希望它只能doSomeSideEffects在某些条件下执行.
我知道你可以做一些接近这个与guard和when了.虽然可以没有嵌套吗?
ExceptT已允许您退出正常流程并返回早期结果.但是ExceptT错误/跳过会传播.我想只跳过本地函数中的其余步骤
doTwoSteps :: MyMonad ()
doTwoSteps = do
  -- if I used ExceptT, an error in the first function will skip the second.
  -- But I still want to do the second step here
  doStuff …我正在研究一些需要在某些关键时刻使用可变数据的更大计算.我想尽可能地避免使用IO.我的模型使用的constist ExceptT超过ReaderT了State数据类型,现在我要替换State有提及ST.
为了简化,假设我想保持单一STRef与Int整个计算过程中,让我们跳过ExceptT外层.我最初的想法是STRef s Int进入ReaderT环境:
{-#LANGUAGE Rank2Types#-}
{-#LANGUAGE ExistentialQuantification#-}
data Env = Env { supply :: forall s. STRef s Int }
data Comp a = forall s. Comp (ReaderT Env (ST s) a)
评估员:
runComp (Comp c) = runST $ do
   s <- newSTRef 0
  runReaderT c (Env {supply = s})  -- this is of type `ST s a`
......它失败了,因为 …
我想尽可能简洁地(但清楚地)将 a 转换List<Triple<String, String, String>为 a Triple<List<String>, List<String>, List<String>>。
例如,假设执行转换的方法被调用turnOver,我希望:
val matches = listOf(
  Triple("a", "1", "foo"),
  Triple("b", "2", "bar"),
  Triple("c", "3", "baz"),
  Triple("d", "4", "qux")
)
val expected = Triple(
  listOf("a", "b", "c", "d"),
  listOf("1", "2", "3", "4"),
  listOf("foo", "bar", "baz", "qux")
)
matches.turnOver() == expected // true
如何编写简洁、清晰且可能具有turnOver功能性的函数?
可以使用 Arrow-Kt,我已经将其作为项目依赖项。
monads functional-programming monad-transformers kotlin arrow-kt
今天早些时候我正在写一些 Haskell。想出了一些类似的东西
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Foo a = Foo { ParsecT String () (Writer DefinitelyAMonoid) a }
    deriving (Functor, Applicative, Monad, MonadWriter DefinitelyAMonoid)
这没有编译。“没有(MonadWriter DefinitelyAMonoid (ParsecT String () (Writer DefinitelyAMonoid)))从数据类型声明的‘派生’子句引起的实例”,GHC 告诉我。所以我决定看看其他一些 MTL 类是否可行,他们确实做到了。Reader和MonadReader,Writer和MonadWriter。所以我转身被 Discord 用户引导到Hackage,问题很明显:
MonadState  s m => MonadState  s (ParsecT s' u m)
MonadReader r m => MonadReader r (ParsecT s  u m)
MonadError  e m => MonadError  e (ParsecT s  u …我有以下代码片段,它有点工作:
launchTask :: (DeviceRepo m) => TaskSpec -> m (Maybe Task)
launchTask taskSpec@TaskSpec { taskSpecImage = image
                             , taskSpecRequirement = requirement
                             } = do
  mayDevice <- getDeviceMatchingRequirement requirement
  case mayDevice of
    Nothing -> return Nothing
    Just device -> do
      mayContainer <- createContainer device requirement
      case mayContainer of
        Nothing -> return Nothing
        Just container ->
          return $
          Just
            Task
              { taskName = pack image
              , taskStatus = TaskStatusRunning
              , taskSpec = taskSpec
              , taskContainerId = containerId container
              }
但是,我觉得这不是很地道。堆叠主要计算(来自 DeviceRepo m)和可能的 …