Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transforming OCaml code to F#

Tags:

f#

ocaml

I'm transforming some OCaml code to F# having a problem with the OCaml let...and... which only exists in F# by using a recursive function. I have the given OCaml code:

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"

which I want to use in these two methods:

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

Has someone any idea how I have to change it that so that I can use it?

like image 838
Hagi Avatar asked Jan 06 '16 01:01

Hagi


2 Answers

It looks like you are trying to translate "Handbook of Practical Logic and Automated Reasoning".

Did you see: An F# version of the book code is now available! Thanks to Eric Taucher, Jack Pappas and Anh-Dung Phan.

You need to look at 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

I asked many questions here while working on the translation and prefixed them with Converting OCaml to F#:. If you look in the comments you will see how the three of us came to work on this project.

like image 52
Guy Coder Avatar answered Nov 15 '22 10:11

Guy Coder


You can just write:

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# tends to be written using lightweight, rather than verbose, syntax so you don't generally need to use the in, begin and end keywords. See: https://msdn.microsoft.com/en-us/library/dd233199.aspx for details about the differences.

Personally, I would probably refactor all of those string -> bool functions into active patterns, e.g.:

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

Then you can pattern match, e.g.:

match c with
|Alphanumeric _ -> // alphanumeric case
|Symbolic _ -> // symbolic case
|_ -> // other cases
like image 37
TheInnerLight Avatar answered Nov 15 '22 11:11

TheInnerLight