F#计算表达式 - 输入困境

时间:2013-12-24 10:58:55

标签: f# monads computation-expression

我正在与一些可怜的代码作斗争,但无法解决这个问题 - 无论出于何种原因,我无法理解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 所以我只需要破坏我在类型系统中获得的语​​法/概念障碍。

2 个答案:

答案 0 :(得分:4)

F#中计算表达式的重点在于,您不必在构建器实例(Bind上显式调用ReturnstrInt等方法。 )。这是letlet!之间的差异 - 在计算表达式中,let!绑定被编译,因此它们调用构建器实例的Bind方法。所以你要写这样的代码:

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

但是 - 上面的代码仍无效,因为您的BindReturn方法未正确定义(它们不是monadic)。我是第二个Patryk的建议(在他的评论中) - 你应该花一些时间练习简单,常见的monad(例如,option),然后再开始尝试编写自己的monad。 使用 F#计算表达式很容易,但定义自己的计算表达式是一个中级/高级主题。

答案 1 :(得分:3)

你已经定义Bind来获取一个tupled参数(这对于计算构建器是正确的),但是你以curry形式传递参数(strInt.Bind a stringToInt而不是strInt.Bind(a, stringToInt) )。