gpt4 book ai didi

c# - Monadic .NET 类型

转载 作者:可可西里 更新时间:2023-11-01 08:47:54 25 4
gpt4 key购买 nike

In a great series of posts Eric Lippert 为 .NET 类型概述了所谓的“Monad 模式”,这些类型的行为有点像 monad 并为其中一些类型实现 return 和 bind。

作为一元类型的例子,他给出了:

  • Nullable<T>
  • Func<T>
  • Lazy<T>
  • Task<T>
  • IEnumerable<T>

我有两个问题:

  1. 我明白了 Nullable<T>有点像 Maybe在 Haskell 中绑定(bind)多个 Maybe actions 表示一组可能在任何时候失败的操作。我知道列表 monad ( IEnumerable<T> ) 代表非确定性。我什至有点明白什么Func作为 monad(Reader monad)。Lazy<T> 的单子(monad)语义是什么?和 Task<T> ?绑定(bind)他们是什么意思?

  2. 是否有人在 .NET 中有更多类似 monad 的类型示例?

最佳答案

好吧,Haskell 默认有惰性,所以这在 Haskell 中不是很有启发性,但我仍然可以展示如何将 Task 实现为 monad。以下是如何在 Haskell 中实现它们:

import Control.Concurrent.Async (async, wait)

newtype Task a = Task { fork :: IO (IO a) }

newTask :: IO a -> Task a
newTask io = Task $ do
w <- async io
return (wait w)

instance Monad Task where
return a = Task $ return (return a)
m >>= f = newTask $ do
aFut <- fork m
a <- aFut
bFut <- fork (f a)
bFut

为方便起见,它建立在 async 库之上,但并非必须如此。 async 函数所做的就是派生一个线程来评估一个 Action ,返回一个 future 。我只是围绕它定义了一个小的包装器,这样我就可以定义一个 Monad 实例。

使用此 API,您可以轻松定义自己的 Task,只需在 Task 运行时提供您想要 fork 的操作即可:

import Control.Concurrent (threadDelay)

test1 :: Task Int
test1 = newTask $ do
threadDelay 1000000 -- Wait 1 second
putStrLn "Hello,"
return 1

test2 :: Task Int
test2 = newTask $ do
threadDelay 1000000
putStrLn " world!"
return 2

然后您可以使用 do 符号组合 Task,这会创建一个准备运行的新延迟任务:

test3 :: Task Int
test3 = do
n1 <- test1
n2 <- test2
return (n1 + n2)

运行 fork test3 将生成 Task 并返回一个 future ,您可以随时调用它来要求结果,必要时阻塞直到完成。

为了证明它有效,我将进行两个简单的测试。首先,我将 fork test3 而不要求它的 future ,只是为了确保它正确地生成复合线程:

main = do
fork test3
getLine -- wait without demanding the future

这可以正常工作:

$ ./task
Hello,
world!
<Enter>
$

现在我们可以测试当我们要求结果时会发生什么:

main = do
fut <- fork test3
n <- fut -- block until 'test3' is done
print n

...这也有效:

$ ./task
Hello,
world!
3
$

关于c# - Monadic .NET 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16266696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com