如何编写 Monad 以将计算链接在一起
How To Write a Monad to Chain Computations Together
我正在编写我的第一个 monad 实例,所以如果我遗漏了一些明显的东西,请原谅。
我想做这样的事情:
readStuffFromDatabase >>= function1 >>= ... >>= functionN >>= writeStuffToDatabase
function1 ... functionN 是业务逻辑。任何业务逻辑都可以 return DoNothing,这显然会阻止任何进一步的计算。
这是我的问题:
我是否以正确的方式思考问题?这种方法能否带来惯用的代码、良好的性能等,还是它已经注定了?
我应该如何定义一个旨在将任意数量的计算链接在一起的类型?对我来说模糊的是所有的 monad 实例都已经这样做了,我需要的只是一个普通的 monad 实例吗? (比如 Maybe?)或者我需要更复杂的东西吗?
简短版本:Monad
几乎肯定会把你逼到墙角。您需要 Applicative
,或者最多需要一个选择性应用程序。
假设您选择一个 monad,将其命名为 M
,并执行一些操作,例如 numEmployees :: M Int
之类的。现在我写:
do
n <- numEmployees
if n > 10
then computeTaxes
else dollars 1000 <$ DoNothing
要执行此操作,您需要在知道 n
之前决定是否采用 else
分支。不可能。
单子的基本特征是,后面的动作可以在决定做什么之前检查前面的动作返回的值。 Applicative functor 不支持它,因此更适合您希望进行的那种静态分析。
我正在编写我的第一个 monad 实例,所以如果我遗漏了一些明显的东西,请原谅。
我想做这样的事情:
readStuffFromDatabase >>= function1 >>= ... >>= functionN >>= writeStuffToDatabase
function1 ... functionN 是业务逻辑。任何业务逻辑都可以 return DoNothing,这显然会阻止任何进一步的计算。
这是我的问题:
我是否以正确的方式思考问题?这种方法能否带来惯用的代码、良好的性能等,还是它已经注定了?
我应该如何定义一个旨在将任意数量的计算链接在一起的类型?对我来说模糊的是所有的 monad 实例都已经这样做了,我需要的只是一个普通的 monad 实例吗? (比如 Maybe?)或者我需要更复杂的东西吗?
简短版本:Monad
几乎肯定会把你逼到墙角。您需要 Applicative
,或者最多需要一个选择性应用程序。
假设您选择一个 monad,将其命名为 M
,并执行一些操作,例如 numEmployees :: M Int
之类的。现在我写:
do
n <- numEmployees
if n > 10
then computeTaxes
else dollars 1000 <$ DoNothing
要执行此操作,您需要在知道 n
之前决定是否采用 else
分支。不可能。
单子的基本特征是,后面的动作可以在决定做什么之前检查前面的动作返回的值。 Applicative functor 不支持它,因此更适合您希望进行的那种静态分析。