有没有办法对 do! 进行不同的实现?让!在计算表达式中?
我需要不同的行为来做!让!在我的自定义计算表达式中。
我尝试通过以下方式实现此目的:
type FooBuilder() = class
member b.Bind<'T, 'U>(x:'T, f:unit->'U):'U = failwith "not implemented" //do! implementation
member b.Bind<'T, 'U>(x:'T, f:'T->'U):'U = failwith "not implemented" //let! implementation
member b.Return<'T>(x:'T):'T = failwith "not implemented" //return implementation
end
let foo = FooBuilder()
let x = foo {
do! ()
return 2
}
但是编译器给了我一个错误:
无法根据此程序点之前的类型信息确定方法“Bind”的唯一重载。可用的重载如下所示(或在“错误列表”窗口中)。可能需要类型注释。
有没有办法有不同的实现 do!并让!?
I need a different behavior for do! and let! in my custom computation expression.
I try to achieve this in the following way:
type FooBuilder() = class
member b.Bind<'T, 'U>(x:'T, f:unit->'U):'U = failwith "not implemented" //do! implementation
member b.Bind<'T, 'U>(x:'T, f:'T->'U):'U = failwith "not implemented" //let! implementation
member b.Return<'T>(x:'T):'T = failwith "not implemented" //return implementation
end
let foo = FooBuilder()
let x = foo {
do! ()
return 2
}
But compiler gives me an error:
A unique overload for method 'Bind' could not be determined based on type information prior to this program point. The available overloads are shown below (or in the Error List window). A type annotation may be needed.
Is there a way to have a different implementation of do! and let!?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您想保持
let!
中使用的Bind
操作通用,那么就没有办法说 F# 在翻译do! (重载必然必须重叠)。
一般来说,如果您希望
let!
和do!
获得不同的行为,那么这表明您的计算表达式可能定义不正确。这个概念非常灵活,它可以用于更多的事情,而不仅仅是声明 monad,但你可能把它延伸得太远了。如果您可以写下有关您想要实现的目标的更多信息,那将会很有用。无论如何,这里有一些可能的解决方法...您可以添加一些额外的包装并编写类似
do! 的内容。换行<|表达式
。另一种选择是使用动态类型测试。这有点低效(而且有点不优雅),但它可能会起作用,具体取决于您的场景:
但是,当您编写
let! 时,这仍然会使用
。do!
重载。 () = 条If you want to keep the
Bind
operation used inlet!
generic, then there is no way to say that F# should use different implementation when translatingdo!
(the overloads will necessarily have to overlap).In general, if you want to get different behavior for
let!
and fordo!
then it suggests that your computation expression is probably incorrectly defined. The concept is quite flexible and it can be used for more things than just for declaring monads, but you may be stretching it too far. If you can write more information about what you want to achieve, that would be useful. Anyway, here are some possible workarounds...You can add some additional wrapping and write something like
do! wrap <| expr
.Another alternative would be to use dynamic type tests. This is a bit inefficient (and a bit inelegant), but it may do the trick, depending on your scenario:
However, this would still use the
do!
overload when you writelet! () = bar
.您可以尝试其他方法,有点难看,但应该可以工作:
它装箱 a (将其转换为 obj )并检查它是否为unit 类型,然后重定向到正确的过载。
You could try something else, a bit ugly, but should work:
It boxes a (converts it to
obj
) and checks if it is of typeunit
, then redirects to the correct overload.