将OCaml代码转换为F#

5

我正在将一些OCaml代码转换为F#,在使用递归函数解决OCaml中的let...and...问题时遇到了困难。

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

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

2个回答

7

看起来你正在尝试翻译 "实用逻辑与自动推理手册"

你是否看到:现在有该书代码的F#版本可用!感谢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

在翻译过程中,我曾在此处提出许多与编程有关的问题,并在前面加上了将OCaml转换为F#:。如果您查看评论,您会看到我们三个人是如何一起合作完成这个项目的。


哇,你让这变得很容易。非常感谢。 - Hagi
你是想使用这本书还是只需要那段代码? - Guy Coder
我正在尝试使用这本书并将其翻译。我遇到了一个问题,但是没有找到解决方案。@程序员盖伊 - Hagi
由于您也尝试翻译代码,请注意 initialization.fs、lib.fs 并阅读注释。翻译代码最困难的部分不是代码本身,而是环境之间的差异。例如,OCaml 有预处理器而 F# 没有等等。 - Guy Coder
另外,如果想查看OCaml下所有代码的运行情况,请参阅OCaml Results.pdf - Guy Coder
显示剩余2条评论

3

您只需要写:

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 -> 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

谢谢,我用了这些关键字因为它们有效,但是模式匹配看起来不错。 - Hagi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接