我如何使用 (->) r Monad 或其他 (->) r type class 实例在这里可能有用来简化函数应用程序?
How can I simplify function application with (->) r Monad or which other (->) r type class instance may be useful here?
例如我有以下代码:
func1 :: a -> b
func3 :: b -> b -> b -> c
myExample x y z = func3 (func1 x) (func1 y) (func1 z)
对这种情况有什么一般性建议吗?
Monad 的 (->) r
实例可以被认为是向(多个)函数提供 "supply of r
"。它的使用示例可能是:
example f g h x = f (g x) (h x)
会变成
example' f g h = do
x1 <- g
x2 <- h
return (f x1 x2)
其中参数(最初 x
)被提供给每个函数。
您的示例没有为多个函数提供 r
的单一供应,而是为单个函数提供多个 r
值。这不是 Monad 的 (->) r
实例的用例。
(->) r
monad 并不是真的"simplify application."应用函数最简单的方法就是应用函数!
我发现感受 (->) r
的最直观方式是它允许您 对共享相同参数类型的函数的结果类型进行操作 .比如说你有这些功能:
f :: a -> b -> c
g :: r -> a
h :: r -> b
在这种情况下,请注意:
f
对 g
和 h
的结果类型进行操作。
g
和 h
共享相同的参数类型。
现在为 (->) r
使用 Applicative
实例(Monad
的超类),你可以这样写:
import Control.Applicative (liftA2)
example :: r -> c
example = liftA2 f g h
因此,如果您有许多函数都采用类型为 r
的共享 "context" 参数,并且您的代码到处都是线程,有时您可以通过使用 Reader r
monad(这只是 (->) r
周围的 newtype
)编写代码,"pretends" 已经提供了上下文值。
扩展我对这个答案的第一条评论,考虑到你到目前为止告诉我们的关于你的例子的内容,我没有看到使用任何这种机器的情况。在这个定义中:
myExample x y z = func3 (func1 x) (func1 y) (func1 z)
...func1
应用于三个不同的值,因此以下内容不等价:
notYourExample = liftA3 func3 func1 func1 func1
这相当于:
notYourExample x = func3 (func1 x) (func1 x) (func1 x)
函数中重复的不是 func1
的参数,而是 func1
本身。您可以使用 (->) r
monad 通过应用一些代码 golf:
来消除重复
myExample x y z = liftA3 func3 ($x) ($y) ($z) func1
你觉得比原著难读吗?好吧,这就是不这样做的原因!它也可能不严格等同于您的示例,具体取决于 func1
.
的精确类型
例如我有以下代码:
func1 :: a -> b
func3 :: b -> b -> b -> c
myExample x y z = func3 (func1 x) (func1 y) (func1 z)
对这种情况有什么一般性建议吗?
Monad 的 (->) r
实例可以被认为是向(多个)函数提供 "supply of r
"。它的使用示例可能是:
example f g h x = f (g x) (h x)
会变成
example' f g h = do
x1 <- g
x2 <- h
return (f x1 x2)
其中参数(最初 x
)被提供给每个函数。
您的示例没有为多个函数提供 r
的单一供应,而是为单个函数提供多个 r
值。这不是 Monad 的 (->) r
实例的用例。
(->) r
monad 并不是真的"simplify application."应用函数最简单的方法就是应用函数!
我发现感受 (->) r
的最直观方式是它允许您 对共享相同参数类型的函数的结果类型进行操作 .比如说你有这些功能:
f :: a -> b -> c
g :: r -> a
h :: r -> b
在这种情况下,请注意:
f
对g
和h
的结果类型进行操作。g
和h
共享相同的参数类型。
现在为 (->) r
使用 Applicative
实例(Monad
的超类),你可以这样写:
import Control.Applicative (liftA2)
example :: r -> c
example = liftA2 f g h
因此,如果您有许多函数都采用类型为 r
的共享 "context" 参数,并且您的代码到处都是线程,有时您可以通过使用 Reader r
monad(这只是 (->) r
周围的 newtype
)编写代码,"pretends" 已经提供了上下文值。
扩展我对这个答案的第一条评论,考虑到你到目前为止告诉我们的关于你的例子的内容,我没有看到使用任何这种机器的情况。在这个定义中:
myExample x y z = func3 (func1 x) (func1 y) (func1 z)
...func1
应用于三个不同的值,因此以下内容不等价:
notYourExample = liftA3 func3 func1 func1 func1
这相当于:
notYourExample x = func3 (func1 x) (func1 x) (func1 x)
函数中重复的不是 func1
的参数,而是 func1
本身。您可以使用 (->) r
monad 通过应用一些代码 golf:
myExample x y z = liftA3 func3 ($x) ($y) ($z) func1
你觉得比原著难读吗?好吧,这就是不这样做的原因!它也可能不严格等同于您的示例,具体取决于 func1
.