我正在与一些可怜的代码作斗争,但无法解决这个问题 - 无论出于何种原因,我无法理解F#类型系统的这一方面的原则,到目前为止我所有的阅读都没有工作。
有人能向我指出我在这里犯的相当愚蠢的小学生错误吗?我知道我正在制作一个,我只是看不到它!我正试图从这个痛苦的初学者的土地上爬出来,所以完全遵循为什么这不起作用的原则是我的目标 - 任何帮助都会感激不尽!
这是一个简单的练习 - 只是练习一个实际上并不需要monad来执行,但是我真的希望这些东西在我的下一个项目中。
let stringToInt str = Int32.TryParse(str)
type wk() =
member this.Bind(f , str) = f str
member this.Return(f ) = f
let strInt = new wk()
let test a = strInt{let! b = strInt.Bind a stringToInt
return b}
let x = test "10"
printfn "%s" x
我得到以下内容:
Program.fs(117,14): error FS0001: This expression was expected to have type
(string -> bool * int) -> ('a -> 'a) -> 'b
but here has type string
更新:根据以下方面的帮助,我现在有了这个工作:
open System
open System.Threading
let stringToInt str = snd <| Int32.TryParse(str)
type wk() =
member this.Bind(funct, str) = funct str
member this.Return(str) = str
let strInt = new wk()
//Jack P syntax!
let test2 str funct = strInt{
let! b = funct str
return b
}
let go2 = test2 ("10", stringToInt) |> printfn "%A"
虽然工作可能在概念上还没有 - 但是没有发生打印的价值。我会继续黑客攻击 - 我已经完成了大量的阅读,这就是我从中获得练习的地方,但我认为这个概念的唯一方法就是继续与之抗争。
我在博客上以一种更简单的形式取得了成功:http://richardgriffiths.azurewebsites.net/?p=2332 所以我只需要破坏我在类型系统中获得的语法/概念障碍。
答案 0 :(得分:4)
F#中计算表达式的重点在于,您不必在构建器实例(Bind
上显式调用Return
,strInt
等方法。 )。这是let
和let!
之间的差异 - 在计算表达式中,let!
绑定被编译,因此它们调用构建器实例的Bind
方法。所以你要写这样的代码:
let test a =
strInt {
let! b = stringToInt a
return b
}
但是 - 上面的代码仍无效,因为您的Bind
和Return
方法未正确定义(它们不是monadic)。我是第二个Patryk的建议(在他的评论中) - 你应该花一些时间练习简单,常见的monad(例如,option
),然后再开始尝试编写自己的monad。 使用 F#计算表达式很容易,但定义自己的计算表达式是一个中级/高级主题。
答案 1 :(得分:3)
你已经定义Bind
来获取一个tupled参数(这对于计算构建器是正确的),但是你以curry形式传递参数(strInt.Bind a stringToInt
而不是strInt.Bind(a, stringToInt)
)。