标签: monad-transformers

Scala 中的 Monad 变形金刚

我一直在尝试简单的 Monad Transformers,其中我对涉及M[F[A]]whereMFare monad 的理解。如果是不同的单子,我如何在 for comp 中一起制作M[F[A]]和工作?M[S[A]]S

例如:

val a: Future[List[Int]] = ...
val b: Future[Option[Int]] = ...
Run Code Online (Sandbox Code Playgroud)

a需要 aListT[Future, Int]b需要 anOptionT[Future, Int]但这些不组成,我需要使用另一个变压器吗?这取决于我在 for comp 中使用它们的顺序吗?

monads scala monad-transformers scalaz

3
推荐指数
1
解决办法
292
查看次数

throwE 和 catchE 以及 exceptT monad 位于 Monadic 堆栈的底部

假设我有一个像这样的单子堆栈:

import Control.Monad.Trans.Reader
import Control.Monad.Trans.Except
import Control.Monad.Trans

type MyMonad = ReaderT Env (ExceptT String IO) -- Env is irrelevant
Run Code Online (Sandbox Code Playgroud)

和一个函数(简化,但想法成立):

f :: Integer -> MyMonad Integer
f 42 = lift $ throwE "42 is an ILLEGAL number"
f n = return n
Run Code Online (Sandbox Code Playgroud)

我现在想做的是f从另一个函数调用,但如果发生则捕获抛出的异常并以某种方式处理它(例如,抛出另一个异常但消息已更改)。我很难弄清楚应该在这里进行什么样的电梯操作才能正确完成。我尝试过这样的事情:

g n = do
  x <- (f n) `catchE'` (\_ -> lift $ throwE "nope, still illegal")
  return x
where catchE' - lift . catchE
Run Code Online (Sandbox Code Playgroud)

但它显然行不通,因为catchE'在 monad 中需要一些东西ExceptT,而不是MyMonad. 可以轻松完成吗?也许改变 …

monads haskell exception monad-transformers

3
推荐指数
1
解决办法
238
查看次数

使用 FSharpPlus 的 Reader monad 转换器示例

我试图理解读者单子转换器。我正在使用FSharpPlus并尝试编译以下示例,该示例首先从阅读器环境中读取某些内容,然后执行一些异步计算,最后合并两个结果:

open FSharpPlus
open FSharpPlus.Data

let sampleReader = monad {
    let! value = ask
    return value * 2
}

let sampleWorkflow = monad {
    do! Async.Sleep 5000
    return 4
}

let doWork = monad {
    let! envValue = sampleReader
    let! workValue = liftAsync sampleWorkflow
    return envValue + workValue
}

ReaderT.run doWork 3 |> Async.RunSynchronously |> printfn "Result: %d"
Run Code Online (Sandbox Code Playgroud)

有了这个,我在它显示的行出现编译错误,let! value = ask并显示以下完全无用的(至少对我来说)错误消息:

将默认类型“obj”应用于类型推断变量时,类型约束不匹配。没有与方法“op_GreaterGreaterEquals”匹配的重载。

已知返回类型:异步

已知类型参数:< obj , (int -> Async) >

感觉就像我只是在某个地方缺少一些操作员,但我无法弄清楚。

f# monad-transformers f#+

3
推荐指数
1
解决办法
718
查看次数

理解 Monad Transformers 的困难

我希望获得一些有助于理解 Monad Transformer 的信息,以及与此相关的使用do符号会发生什么。我试图理解的例子如下:

data ProtectedData a = ProtectedData String a

accessData :: String -> ProtectedData a -> Maybe a
accessData s (ProtectedData pass v) =
    if s == pass then Just v else Nothing


type Protected s a = MaybeT (Reader (ProtectedData s)) a

-- untangles the monad construction
run :: ProtectedData s -> Protected s a -> Maybe a
run ps psa = runReader (runMaybeT psa) ps

access :: String -> Protected a a
access pass …
Run Code Online (Sandbox Code Playgroud)

monads haskell functional-programming monad-transformers

3
推荐指数
1
解决办法
155
查看次数

这个概念在 Haskell 中叫什么?

我正在用 C++ 编写一些相对函数式风格的代码,并试图避免为其起一个坏名字。为此,我尽可能坚持 Haskell 中同构概念的名称。(需要明确的是,我不太了解 Haskell,但阅读它非常有启发性。)

如果我正确地完成了 Haskell 打字,我相信我正在寻找名称的概念将具有以下签名:

someName :: (Monad m1, Monad m2) => (a -> m1 b) -> (m2 a -> m1 m2 b)
Run Code Online (Sandbox Code Playgroud)

这个想法是,您有一个适合用于绑定类型 monad 的函数m1,并将其转换为适合绑定m1包含m2值的值的函数。

我不能很好地编写 Haskell 来给出一个例子,但这里是伪 C++ 说明我想要的,使用std::optionalabsl::StatusOr

// A silly example of a bind function for absl::StatusOr<int>.
absl::StatusOr<int> AddTwoUnless17(int x) {
  if (x == 17) {
    return absl::InternalError("can't add two to 17!")
  }
  
  return x + 2;
}

// Convert AddTwoUnless17 into …
Run Code Online (Sandbox Code Playgroud)

monads haskell functional-programming monad-transformers

3
推荐指数
1
解决办法
173
查看次数

为Text.JSON的Result类型编写liftIO实例

Haskell的Text.JSON库使用一个名为Result的抽象数据类型,它基本上是它们的Maybe形式,但是没有Nothing,就有错误字符串.Anywho,我需要使用liftIO转换一个函数调用,将一个IO事件返回到我的JSON.readJSON实现中的Result事物.我是monad变换器的新手,似乎无法为Result实现liftIO(我继续尝试构造无限类型,根据ghci).

有任何想法吗?

非常感谢

编辑

对不起,我花了很长时间来详细说明!我感谢你的帮助.

  readJSON (JSObject obj) = do text <- getVal obj "text"
                           user <- getVal obj "from_user"
                           iden <- getVal obj "id_str"
                           url <- (do if (length.extractURLs) text == 0
                                           then return ""
                                           else return $ head $ extractURLs text)
                           title <- liftIO (getSiteTitle url)
                           return $ 
                            Tweet 
                              NewsStory {
                                          title = "Twitter",
                                          desc = text,
                                          url = url,
                                          metric = 0,
                                          sourceURL = "twitter.com/" ++ user  ++ "/status/" ++ iden
                                        }
Run Code Online (Sandbox Code Playgroud)

因此返回前的最后一行使用getSiteTitle来解析该URL的网站以获取其标题.但是,该函数返回一种IO字符串,编译器告诉我它希望它是Result.这不可能吗?

再次感谢!

EDIT2

我决定从我的数据类型中删除标题,然后在IO monad中获取它.谢谢大家的帮助!我当然从这个问题中吸取了教训.

monads json haskell monad-transformers

2
推荐指数
1
解决办法
528
查看次数

一些monad包装/展开/绑定混乱涉及包含Maybe的容器

这是一些示例代码

foo :: a -> Identity (Maybe a)
foo a = do
  maybeStuff <- getStuffSometimes a
  return $ case maybeStuff of                  -- this "case" stuff is the kind
    Just stuff -> Just $ getStuffAlways stuff  -- of code I'd expect the Maybe
    Nothing -> Nothing                         -- monad to help with

getStuffSometimes :: a -> Identity (Maybe a)
getStuffSometimes a = return $ Just a

getStuffAlways :: a -> Identity a
getStuffAlways = return

-- ERROR (on the return statement of …
Run Code Online (Sandbox Code Playgroud)

monads haskell monad-transformers

2
推荐指数
1
解决办法
189
查看次数

如何在没有lambda表达式的情况下编写这些

我正在使用此代码的第一个版本StateT L8.ByteString Maybe a.到目前为止,我已将大部分功能转化为此功能

matchHeader :: L8.ByteString -> StateT L8.ByteString Maybe ()
matchHeader prefix = StateT $ \str ->
      if prefix `L8.isPrefixOf` str
         then Just ((), L8.drop (L8.length prefix) str)
         else Nothing

getNat :: Num a => StateT L8.ByteString Maybe a
getNat = StateT $ \str ->
  case L8.readInt str of
    Nothing -> Nothing
    Just (num, rest)
      | num <= 0        -> Nothing
      | otherwise       -> Just (fromIntegral num, rest)

getBytes :: Integer -> StateT L8.ByteString …
Run Code Online (Sandbox Code Playgroud)

lambda haskell monad-transformers

2
推荐指数
1
解决办法
142
查看次数

Haskell - 使用StateT monad变换器链接两个州

我有两个或更多独立状态要在一个Haskell应用程序中跟踪.

我正在使用声明两个新类型

type MonadTuple m = MonadState (Int, Int) m
type MonadBool m = MonadState Bool m
Run Code Online (Sandbox Code Playgroud)

monad变换器堆栈声明为

type Stack = StateT (Int, Int) (StateT Bool IO) ()
Run Code Online (Sandbox Code Playgroud)

我打算像这样使用堆栈

ret :: Stack
ret = apply

apply :: (MonadTuple m, MonadBool m) => m ()
apply = undefined
Run Code Online (Sandbox Code Playgroud)

该编译器是不高兴,因为它不能匹配Bool(Int, Int)试图检查时Stack符合MonadBool.

我知道在StateT中组合多个状态时给出的解决方案.除了箭头带镜头的全局状态之外,还有其他更简单的解决方案吗?

附录:完整的代码块是

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}

import Control.Monad.State.Class
import Control.Monad.State.Lazy

type MonadTuple m …
Run Code Online (Sandbox Code Playgroud)

haskell state-monad monad-transformers

2
推荐指数
1
解决办法
319
查看次数

使用"bind"与异步函数

假设我有一些返回的函数Async<Result<string>>:

let getData id = async {
   return Ok (string id)
}
Run Code Online (Sandbox Code Playgroud)

现在,此函数的输入是另一个返回函数的结果Result<int>.

我正在努力研究如何Result.bind在异步CE内部组合2 .

例如:

let main = async {
    let id = Ok 123
    let! x = id |> Result.bind getData

    return x
}
Run Code Online (Sandbox Code Playgroud)

这不起作用,我收到错误:

error FS0001: Type mismatch. Expecting a
    'Result<int,'a> -> Async<'b>'    
but given a
    'Result<int,'a> -> Result<'c,'a>'   
Run Code Online (Sandbox Code Playgroud)

或者如果我不使用let!我得到并且只是使用let

error FS0001: Type mismatch. Expecting a
    'int -> Result<'a,'b>'    
but given a
    'int -> Async<Result<string,'c>>
Run Code Online (Sandbox Code Playgroud)

我见过一些答案是说没有使用Result<'a>,只是让异步异常处理做了艰苦的工作,但我面对同样的问题 …

f# monad-transformers

2
推荐指数
1
解决办法
341
查看次数