As I use a lot Printf.fprintf stdout ... in my programs, I would like to rename it by a shorter function. So I write:
let p = Printf.fprintf stdout
And I would hope p "%s" "string" works. However, the compilation gives an error:
File "lib/utility.ml", line 27, characters 8-29:
Error: The type of this expression, ('_a, out_channel, unit) format -> '_a,
contains type variables that cannot be generalized
Does anyone have an idea to rename it so that the application could be as simple as possible?
I think it will work if you eta-expand your definition:
let p fmt = Printf.fprintf stdout fmt
Related
I am completely new to F#.
I am trying to parse a markdown file which has some verbatim code sections in it, separated by the ``` blocks. These blocks neednot be the only characters in a line and
\``` this is some code ``` and this is not
is a valid line as well.
If possible, I'd appreciate if the solution uses pure Fsharp way of doing things and perhaps functional designs patterns like Active Patterns.
So far I haven't gone much further than just reading the file.
open System
open System.IO
let readFile path =
File.ReadAllText(path)
// File.ReadAllLines
[<EntryPoint>]
let main argv =
readFile "src/main.md"
|> String.collect (fun ch -> sprintf "%c " ch)
|> printfn "%s"
0
EDIT: I do not want to use any libraries. In Python, this would be a one line code;
re.search('start;(.*)end', s)
The best way to parse Markdown is to use a library designed to parse Markdown, such as FSharp.Formatting. It's really not a wheel you'll want to reinvent, especially if you're new to F#. Usage example:
open FSharp.Markdown
let markdownText = """
# Some document
Here is a document with a code block
```fsharp
let example = "Foo
```
Here is more text"""
let parsed = Markdown.Parse(markdownText)
printfn "%A" parsed
And since you're interested in an F#-idiomatic solution, take a look at the source for FSharp.Formatting's Markdown parser: plenty of discriminated unions, active patterns, and so on.
We are writing a compiler in OCaml for our own domain specific language. So far, we have working scanner, parser and ast.
What is the best way to test scanner/parser at this point? I know it is possible to pass a sequence of tokens to the parser/scanner and see if it gets accepted/rejected by the scanner/parser. (such as, echo "FLOAT ID" | menhir --interpret --interpret-show-cst parser.mly).
But, is there a way to pass the actual program written in our own language to the scanner/parser and see whether it gets accepted?
I have to add that I am very new to OCaml and I know very little about compilers.
If what you want to do is to give a string to your parser and see if it works, you could do this (supposing your starting point in the parser is prog)
main.ml :
let () =
(* Taking the string given as a parameter or the program *)
let lb = Lexing.from_string Sys.argv.(1) in
(* if you want to parse a file you should write :
let ci = open_in filename in
let lb = Lexing.from_channel ci in
*)
try
let p = Parser.prog Lexer.token lb in
Printf.printf "OK\n"
with _ -> Printf.printf "Not OK\n"
Did I help ? ;-)
I've got a haskell file:
main = putStrLn "hello world"
let a=1
show a
and ghc says:
main.hs:3:1:
parse error (possibly incorrect indentation or mismatched brackets)
There are a number of problems here.
First, if you want to sequence expressions in IO you need to place them in a do block. Second, you need to use indentation (spaces only, no tabs!) to delimit the do block, like so:
main = do
putStrLn "hello world"
let a=1
show a
Finally, show a will return a string, but you want an IO action that prints a string, so it should be putStrLn (show a), or you can use print a as the print function is the composition of showing (turning into a string) and then printing out to the console.
I am trying to experiment in F# for one of the utility tools we need, wherein we want to trawl through a folder of xml files and look for a particular tag. If found then insert another similar tag alongwith it. Finally, output all the filenames for which such additional tags have been inserted. But am getting a compilation error, of which I am not able to make a lot of sense.
let configFile =
Directory.GetFiles(Path.Combine("rootdir", "relativepath"), #"*.xml")
|> Seq.map(fun configFileName ->
let xmlNavigator = XPathDocument(configFileName).CreateNavigator()
let node = xmlNavigator.SelectSingleNode(#"Product/ABc[#type='xyz']")
match node with
| null -> "not configuration present"
| _ ->
let nodeAppender() = node.InsertAfter("<Risk type=""abc1"" methodology=""xyz1""/>")
let parentNode = node.SelectAncestors(XPathNodeType.Root, false)
parentNode.Current.OuterXml)
|> Seq.iter (printfn "%s")
The compilation error is as below:
This value is not a function and cannot be applied
Your string is escaped improperly. It should be:
node.InsertAfter("<Risk type=\"abc1\" methodology=\"xyz1\"/>")
EDIT: Apparently I was typing this as Brian posted his answer. Either escaping each quote char or prefixing with # as-is will work.
It would help to point out what line/column the error location is at.
At a glance, in nodeAppender, it looks like you left off the # on the string literal, which means it is five strings in a row (rather than one string with escaped quotes), which may be the cause of the error.
I am writing my first F# library
I am trying to use string.Format and it complains that no such function exists.
Is it not available or am I doing something wrong?
If you want to avoid using the full name, you can use open in F#:
open System
let s = String.Format("Hello {0}", "world")
This should work in both F# interactive (enter the open clause first) and in normal compiled applications. The key thing is that you must write String with upper-case S. This is because string in C# isn't a usual type name - it is a keyword refering to the System.String type.
Alternatively, you could also take a look at the sprintf function. It is an F#-specific alternative to String.Format which has some nice benefits - for example it is type checked:
let s = sprintf "Hello %s! Number is %d" "world" 42
The compiler will check that the parameters (string and int) match the format specifiers (%s for string and %d for integers). The function also works better in scenarios where you want to use partial function application:
let nums = [ 1 .. 10 ]
let formatted = nums |> List.map (sprintf "number %d")
This will produce a list of strings containing "number 1", "number 2" etc... If you wanted to do this using String.Format, you'd have to explicitly write a lambda function.
the full name of it is:
System.String.Format