0

我正在与几行可悲的代码作斗争,但无法解决这个问题——无论出于何种原因,我都无法理解 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 所以我只需要打破类型系统的语法/概念障碍。

4

2 回答 2

4

F# 中计算表达式的全部意义在于您不必在构建器实例上显式调用BindReturn等方法(strInt在您的情况下)。let这就是和之间的区别let!——在计算表达式中,let!绑定被编译,因此它们调用Bind构建器实例的方法。所以你会这样写你的代码:

let test a =
    strInt {
    let! b  = stringToInt a
    return b
    }

但是 - 上面的代码仍然不起作用,因为您的BindandReturn方法没有正确定义(它们不是一元的)。option我赞同 Patryk 的建议(在他的评论中)——在开始尝试编写自己的单子之前,您应该花一些时间练习简单、常见的单子(例如, )。使用F# 计算表达式很容易,但定义自己的计算表达式是一个中级/高级主题。

于 2013-12-24T13:37:55.863 回答
3

您已定义Bind采用元组参数(这对于计算构建器来说是正确的),但是您以 curried 形式(strInt.Bind a stringToInt而不是strInt.Bind(a, stringToInt))传递参数。

于 2013-12-24T13:37:30.030 回答