【问题标题】:Transforming OCaml code to F#将 OCaml 代码转换为 F#
【发布时间】:2016-01-07 06:37:50
【问题描述】:

我正在将一些 OCaml 代码转换为 F#,但 OCaml let...and... 存在问题,该问题仅存在于 F# 中,使用递归函数。 我有给定的 OCaml 代码:

let matches s = let chars = explode s in fun c -> mem c chars
let space = matches " \t\n\r"
and punctuiation = matches "() [] {},"
and symbolic = matches "~'!@#$%^&*-+=|\\:;<>.?/"
and numeric = matches "0123456789"
and alphanumeric = matches "abcdefghijklmopqrstuvwxyz_'ABCDEFGHIJKLMNOPQRSTUVWXYZ"

我想在这两种方法中使用:

let rec lexwhile prop inp = match inp with
c::cs when prop c -> let tok,rest = lexwhile prop cs in c+tok,rest
|_->"",inp

let rec lex inp = 
match snd(lexwhile space inp)with
[]->[]
|c::cs ->let prop = if alphanumeric(c) then alphanumeric
                    else if symbolic(c) then symbolic
                    else fun c ->false in
                    let toktl,rest = lexwhile prop cs in
                    (c+toktl)::lex rest

有人知道我必须如何更改它以便我可以使用它吗?

【问题讨论】:

    标签: f# ocaml


    【解决方案1】:

    您似乎正在尝试翻译“Handbook of Practical Logic and Automated Reasoning”。

    您看到了吗:An F# version of the book code 现已推出!感谢 Eric Taucher、Jack Pappas 和 Anh-Dung Phan。

    你需要看intro.fs

    // pg. 17 
    // ------------------------------------------------------------------------- // 
    // Lexical analysis.                                                         // 
    // ------------------------------------------------------------------------- // 
    
    
    let matches s =  
        let chars =  
            explode s  
        fun c -> mem c chars 
    
    let space = matches " \t\n\r"  
    
    let punctuation = matches "()[]{}," 
    
    let symbolic = matches "~`!@#$%^&*-+=|\\:;<>.?/" 
    
    let numeric = matches "0123456789" 
    
    let alphanumeric = matches "abcdefghijklmnopqrstuvwxyz_'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 
    
    let rec lexwhile prop inp = 
        match inp with 
        | c :: cs when prop c -> 
            let tok, rest = lexwhile prop cs 
            c + tok, rest 
        | _ -> "", inp 
    
    let rec lex inp = 
        match snd <| lexwhile space inp with 
        | [] -> [] 
        | c :: cs -> 
            let prop = 
                if alphanumeric c then alphanumeric 
                else if symbolic c then symbolic 
                else fun c -> false 
            let toktl, rest = lexwhile prop cs 
            (c + toktl) :: lex rest
    

    我在翻译时问了很多questions,并在他们前面加上Converting OCaml to F#:。如果您查看 cmets,您会看到我们三个人是如何参与这个项目的。

    【讨论】:

    • 哇,你让我轻松了。非常感谢。
    • 你是想用这本书还是只需要那段代码?
    • 我正在尝试使用这本书并进行翻译。那只是我没有找到解决方案的问题。 @Guy 编码器
    • 既然您正在尝试使用这本书,请查看所有测试用例以及此wiki page,尤其是Seventy-Five Problems for Testing Automatic Theorem Provers
    • 由于您也在尝试翻译代码,因此请注意initialization.fs,lib.fs并阅读cmets。翻译代码最难的部分不是代码,而是环境的差异。例如 OCaml 有一个预处理器,而 F# 没有,等等。
    【解决方案2】:

    你可以写:

    let explode s = [for c in s -> string c]
    let matches str strc = 
        let eStr = explode str
        List.contains strc eStr 
    let space = matches " \t\n\r"
    let punctuation = matches "() [] {},"
    let symbolic = matches "~'!@#$%^&*-+=|\\:;<>.?/"
    let numeric = matches "0123456789"
    let alphanumeric = matches "abcdefghijklmopqrstuvwxyz_'ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    

    F# 倾向于使用轻量级而非冗长的语法编写,因此您通常不需要使用inbeginend 关键字。有关差异的详细信息,请参阅:https://msdn.microsoft.com/en-us/library/dd233199.aspx

    就个人而言,我可能会将所有这些 string -&gt; bool 函数重构为活动模式,例如:

    let (|Alphanumeric|_|) str =
        match matches "abcdefghijklmopqrstuvwxyz_'ABCDEFGHIJKLMNOPQRSTUVWXYZ" str with
        |true -> Some str
        |false -> None
    
    let (|Symbolic|_|) str =
        match matches "~'!@#$%^&*-+=|\\:;<>.?/" str with
        |true -> Some str
        |false -> None
    

    然后你可以进行模式匹配,例如:

    match c with
    |Alphanumeric _ -> // alphanumeric case
    |Symbolic _ -> // symbolic case
    |_ -> // other cases
    

    【讨论】:

    • 谢谢,我使用了关键字,因为它们有效,但模式匹配看起来不错。
    猜你喜欢
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    • 2012-09-08
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多