OCaml string and Coq string (Extraction from Coq to OCaml) - ocaml

I used the extraction from Coq to OCaml, where I have type Z, N, positive
I don't use to extract it in int of OCaml.
Then the type I have after the extraction is:
type positive =
| Coq_xI of positive
| Coq_xO of positive
| Coq_xH
type coq_N =
| N0
| Npos of positive
type coq_Z =
| Z0
| Zpos of positive
| Zneg of positive
I have a program in OCaml where some functions using the OCaml type string.
In my OCaml program, I need to write some functions convert the type: string -> coq_N, string -> coq_Z, string -> positive
I tried to write the functions in Coq and then used the extraction to get the OCaml type but Coq string is different from OCaml string.
For instance:
open Ascii
open BinNums
open Datatypes
type string =
| EmptyString
| String of ascii * string
let string_of_coqN (s: string): coq_N =
match s with
| EmptyString -> N0
| String (a, _) -> (coq_N_of_ascii a);;
where coq_N_of_ascii is the extraction from coq function N_of_ascii.
When I applied the function string_of_coqN, for instance:
let test (x: string) = string_of_N x;;
I got the complain that
Error: This expression has type string but an expression was expected of type
String0.string
Could you please help me to find a way to write the convert functions : string -> coq_N, string -> coq_Z and string -> positive?

For strings, the easiest thing to do is probably to import the standard library module ExtrOcamlString in your extraction file, which will cause Coq to extract them as a char list in OCaml. You can then convert between char list and native strings with custom code. Have a look for instance at file lib/Camlcoq.v in the CompCert distribution, functions camlstring_of_coqstring and coqstring_of_camlstring.

Related

How to iterate through a pattern and returns a list of all the strings

Hello i am currently doing the course Programing languages and am having difficulties with the following helper function: The function takes a pattern and returns a list of all the strings it uses for variables.
This is the pattern:
datatype pattern = Wildcard
| Variable of string
| UnitP
| ConstP of int
| TupleP of pattern list
| ConstructorP of string * pattern
For example:
val test1007 = helper (ConstructorP("x", (TupleP [Wildcard, Variable "x", ConstructorP("y", TupleP [Variable "y"])]))) = ["x","y"]
I know i have to use some case expression to match for the pattern, but cannot figure it out
Well i had it figured by myself that i have to use case expression, but the problem is that i cannot have no idea what to do afterwards.

How to parse a string into a code structure with TemplateHaskell?

Right now, I have the following piece of code in my project:
embedNarration :: String -> Q Exp
embedNarration file =
let text = unsafePerformIO $ readFile file
parsedMaybe = parseNarration text
succ x = case x of
Left x -> throw $ ErrorCall x
Right x' -> x'
parsed = succ parsedMaybe
res = do parser <- [|((fromRight undefined) . parseNarration)|]
d <- return $ seq parsed text
return $ AppE parser $! LitE $! StringL d
in res
Which is jury-rigged from Data.FileEmbed module's source code. The intention of the code is to generate a Narration (which is a data structure defined in-code) from a resource file.
Right now this quite ugly piece that I don't fully understand tries to parse the resource file; throws a compile-time error if the parse is unsuccessful; or, if the parse is successful, embeds the following piece into the source code:
((fromRight undefined) . parseNarration $ "THE ENTIRE RESOURCE FILE")
Where parseNarration is a function :: String -> Either String Narration
The problem here is the double parsing - the resource file is parsed once during compile time to ensure it's valid, and then the second time during runtime from a string literal. Ideally, I want to, instead of a string literal and a call to the parser, for TemplateHaskell to directly substitute a Narration, so that the parser would only exist during compile-time. But I have no idea how to do this. Surface-level guides to TemplateHaskell and trying to jury-rigg the code further haven't been successful. Is it possible to do? If yes, how?

Combining string modification and concatenation in haskell

So my problem is to take a string in haskell and to modify it so that if there are certain characters, they are changed to other characters, and I have created a helper function to do this, however there is one case where if the character is '!' then it become '!!!111oneone', so i figure to do this you would need to concatenate the current string with '!!111oneone', the trouble is that my function was working with chars however to do this we would need to work with the string, how would you combine this, ie a helper to modify the chars if necessary and implementing the conversion if there is a '!'.
Here is what i have so far
convert :: String -> String
convert [] = []
convert (x:xs) =
| x == '!' = !helper
| otherwise = converthelper x
Assuming your helper is something like
helper :: Char -> String
helper '!' = "!!!111oneone"
helper c = [c]
then you can use concatMap to map helper over each character in your string, and then concatenate the results into a single string.
convert :: String -> String
convert = concatMap helper
-- convert msg = concatMap helper msg
The trick is that your helper promotes every character to a list of characters; most characters just become the corresponding one-character string, but ! becomes something more.
(Note that concatMap forms the basis of the Monad instance for lists. You could also write convert msg = msg >>= helper.)

Haskell output a list of ascii value

For example I have a haskell list [72,73,74,75], how can i output this list as a string?, all elements in the list are ascii value.
You can combine map, that applies a function to each element of a list, and the chr function, that convert an Int value to its Char equivalent:
> map chr [72,73,74,75]
"HIJK"
You can convert an Int code point to a Char using chr :: Int -> Char; a String is just a list of Chars. Note that this'll work for any Unicode code point, not just ASCII, which is something you should be doing anyway.
You can find functions like this using Hoogle; just type something like Int -> Char, and it'll give you functions that match that type.
You can use 'chr' from the module Char to convert the integer values to characters:
import Char
intListToString l = [ chr x | x <- l ]
main = do
putStrLn $ "the string: " ++ (intListToString [72,73,74,75])
Running the above with 'runghci' gives:
the string: HIJK
Do you want this list as a straight string or a list with commas? Unless you want to convert ASCII char values to their character counterparts (which was already covered), you can do the following:
concatMap show [72,73,74,75]
will give you a "72737475" string and
init $ tail $ show [72,73,74,75]
will give you a "72,73,74,75" string

Type errors when using same name

I have 3 files:
1) cpf0.ml
type string = char list
type url = string
type var = string
type name = string
type symbol =
| Symbol_name of name
2) problem.ml:
type symbol =
| Ident of string
3) test.ml
open Problem;;
open Cpf0;;
let symbol b = function
| Symbol_name n -> Ident n
When I combine test.ml: ocamlc -c test.ml.
I received an error:
This expression has type Cpf0.name = char list
but an expression was expected of type string
Could you please help me to correct it? Thank you very much
EDIT: Thank you for your answer. I want to explain more about these 3 files:
Because I am working with extraction in Coq to Ocaml type: cpf0.ml is generated from
cpf.v :
Require Import String.
Definition string := string.
Definition name := string.
Inductive symbol :=
| Symbol_name : name -> symbol.
The code extraction.v:
Set Extraction Optimize.
Extraction Language Ocaml.
Require ExtrOcamlBasic ExtrOcamlString.
Extraction Blacklist cpf list.
where ExtrOcamlString
I opened: open Cpf0;; in problem.ml, and I got a new problem because in problem.ml they have another definition for type string
This expression has type Cpf0.string = char list
but an expression was expected of type Util.StrSet.elt = string
Here is a definition in util.ml defined type string:
module Str = struct type t = string end;;
module StrOrd = Ord.Make (Str);;
module StrSet = Set.Make (StrOrd);;
module StrMap = Map.Make (StrOrd);;
let set_add_chk x s =
if StrSet.mem x s then failwith (x ^ " already declared")
else StrSet.add x s;;
I was trying to change t = string to t = char list, but if I do that I have to change a lot of function it depend on (for example: set_add_chk above). Could you please give me a good idea? how I would do in this case.
EDIT 2: I am sorry to edit this question many times. After follow the answer, I fixed the file problem.ml
type symbol =
| Ident of Cpf0.string
In problem.ml they have another definition like this. And the type one again does not accepted.
module SymbSet = Set.Make (SymbOrd);;
let rec ident_of_symbol = function
| Ident s -> s
let idents_of_symbols s =
SymbSet.fold (fun f s -> StrSet.add (ident_of_symbol f) s) s StrSet.empty;;
This expression has type Cpf0.string = char list but an expression was expected of type Util.StrSet.elt = string
You need to open module Cpf0 in problem.ml because the type string in modules Cfp0 and Problem is not the same.
problem.ml:
open Cpf0
type symbol =
| Ident of string
or better, don't open the module and prefix the type string like this:
type symbol =
| Ident of Cpf0.string