Calling functions in other files in OCaml - ocaml

I have hello.ml that has a length function:
let rec length l =
match l with
[] -> 0
| h::t -> 1 + length t ;;
call.ml that uses the function:
#use "hello.ml" ;;
print_int (length [1;2;4;5;6;7]) ;;
In interpreter mode (ocaml), I can use ocaml call.ml to get the results, but when I tried to compile it with ocamlc or ocamlbuild, I got compilation error.
File "call.ml", line 1, characters 0-1:
Error: Syntax error
Then, how to modify the caller, callee, and build command to compile the code into executables?

The #use directive only works in the toplevel (the interpreter). In compiled code you should use the module name: Hello.length.
I'll show how to build the program from a Unix-like command line. You'll have to adapt this to your environment:
$ ocamlc -o call hello.ml call.ml
$ ./call
6

hello.ml
let rec length l =
match l with
[] -> 0
| h::t -> 1 + length t ;;
call.ml
open Hello
let () = print_int (Hello.length [1;2;4;5;6;7]) ;;
Build
ocamlc -o h hello.ml call.ml
or
ocamlbuild call.native

Related

OCaml Type Matching Error of the project when building

I'm very new to OCaml and I need to build some project from the following https://github.com/janestreet/core_kernel.git.
I try to compile the following source code, which named setup.ml
(* OASIS_START *)
open OASISDynRun;;
open OASISTypes;;
(* OASIS_STOP *)
let () =
InternalInstallPlugin.lib_hook :=
fun (cs, bs, lib) ->
match lib.OASISTypes.lib_findlib_name with
| Some "core_kernel" ->
(cs, bs, lib, [])
| _ ->
(cs, bs, lib, [])
;;
let () = setup ()
With following command
ocamlfind ocamlopt -o $# -linkpkg -package ocamlbuild,oasis.dynrun setup_dev.ml || ocamlfind ocamlc -o $# -linkpkg -package ocamlbuild,oasis.dynrun setup_dev.ml || true
Here is the error message.
File "setup_dev.ml", line 8, characters 8-21:
Error: This pattern matches values of type 'a * 'b * 'c
but a pattern was expected which matches values of type
OASISTypes.common_section * OASISTypes.build_section *
OASISTypes.library * OASISTypes.unix_dirname option
File "setup_dev.ml", line 8, characters 8-21:
Error: This pattern matches values of type 'a * 'b * 'c
but a pattern was expected which matches values of type
OASISTypes.common_section * OASISTypes.build_section *
OASISTypes.library * OASISTypes.unix_dirname option
If you need to take a look at _oasis file, please let me know.
The reason why I use OASIS is that I need to use old version compiler (4.02.0), worrying that some deprecated syntax makes trouble.
Thanks.

Why does feeding init to last not work in Haskell?

So I'm writing a line to get the second to last element of a list. Initially my code was
mySLast x = last.take ((length x) - 1) x
Which worked up until the last function. Realized the my take business is already included in Haskell as init so I rewrote as
mySLast = last.init
This still doesn't work. I find this puzzling because init::[a]->[a] and last::[a]->a so they definitely should be composable morphisms in the Hask Category.
I tried asking Haskell what it thinks the type is and it said
ghci> :t last.init
last.init :: [c] -> c
ghci> last.init [3,2,4,1]
<interactive>:45:6:
Couldn't match expected type ‘a -> [c]’
with actual type ‘[Integer]’
Relevant bindings include
it :: a -> c (bound at <interactive>:45:1)
Possible cause: ‘init’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘init [3, 2, 4, 1]’
In the expression: last . init [3, 2, 4, 1]
Even though
ghci> init [3,2,4,1]
[3,2,4]
ghci> last [3,2,4]
4
So I must be misunderstanding something about composing functions in Haskell. Any insight would be greatly appreciated!
Function application binds more tightly than (.) so
last.init [3,2,4,1]
is being parsed as
last . (init [3,2,4,1])
you can use
(last . init) [3,2,4,1]
or
last . init $ [3,2,4,1]
You forgot the $ between init and your list, e.g.
last . init $ [3,2,4,1]
↑ See here
An alternative solution to this problem that only evaluates the (spine of the) list up to the needed element, rather than using length (which will evaluate the entire spine before walking back to the needed element):
takeTail n xs = go (drop n xs) xs
where
go (_:ys) (_:xs) = go ys xs
go [] xs = xs -- Stop and return xs when ys runs out
> head . takeTail 2 $ [1,2,3,4]
3

Run bash script from ocaml

I think that what i mean is in the title. I have tried to search if it is possible to run bash script from ocaml like from java or from php but i could not find.
i know that we can use ocaml as a scripting language but it is not what i want
Ocaml as a scripting language
In other words
From the Ocaml documentation :
val command : string -> int
So if you want to call a script from Ocaml, do this :
let status = Sys.command "./myexecutable.sh" in
Printf.printf "status = %d\n" status
Feel free to do what you want with the exit code.
Just in case you are interested in collecting the output of the bash script,
let () =
(* Just using pstree as an example, you can pick something else *)
let ic = Unix.open_process_in "pstree" in
let all_input = ref [] in
try
while true do
all_input := input_line oc :: !all_input
done
with
End_of_file ->
(* Just an example, you can do something else here *)
close_in ic;
List.iter print_endline !all_input
I think what you are looking for is the Sys module (http://caml.inria.fr/pub/docs/manual-ocaml/libref/Sys.html).
Sys.command might be one way to do what you want.
If this is not enough, then you may want to take a look at what the Unix has to offer (http://caml.inria.fr/pub/docs/manual-ocaml/libref/Unix.html).

Unit-testing the undefined evaluated in lazy expression in Haskell

Writing a unit test in Haskell where an expression should fail when undefined is encountered is a bit tricky. I tried the following with HSpec:
module Main where
import Test.Hspec
import Control.Exception (evaluate)
main :: IO ()
main = hspec $ do
describe "Test" $ do
it "test case" $ do
evaluate (take 1 $ map (+1) [undefined, 2, 3]) `shouldThrow` anyException
to no avail. It reports me did not get expected exception: SomeException
If I evaluate the same expression in REPL, I'd get:
[*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries\base\GHC\Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:2:20 in interactive:Ghci1
The problem is that evaluate doesn't force your expression to NH or even WHNF1. Try x <- evaluate (take 1 $ map (+1) [undefined, 2, 3]) in GHCi - it doesn't give you any error! The only reason it does when you paste in evaluate (take 1 $ map (+1) [undefined, 2, 3]) is that GHCi also tries to print the result of what it got and, to do that, it ends up trying to evaluate the expression.
If you want to see how much of a thunk has been evaluated, you can always use :sprint in GHCi:
ghci> x <- evaluate (take 1 $ map (+1) [undefined, 2, 3])
ghci> :sprint x
x = [_]
As you can see, evaluate hasn't forced the expression far enough to realize x contains an undefined. A quick fix is to evaluate the thing you are examining to normal form using force.
import Test.Hspec
import Control.Exception (evaluate)
import Control.DeepSeq (force)
main :: IO ()
main = hspec $ do
describe "Test" $ do
it "test case" $ do
evaluate (force (take 1 $ map (+1) [undefined, 2, 3] :: [Int]))
`shouldThrow` anyException
force lets you trigger the evaluation of thunks until the argument is full evaluated. Note that it has an NFData (stands for "normal form data") constraint on it, so you may find yourself deriving Generic and NFData for your data structures.
1 Thanks for #AlexisKing for pointing out that evaluate does push its argument into WNHF, which is why head $ map (+1) [undefined, 2, 3] does trigger the error. In the case of take, it isn't enough though.

Convert a string into array of words

How do I separate a string into a list/array of white space separated words.
let x = "this is my sentence";;
And store them inan list/array like this:
["this", "is", "my", "sentence"]
Using the standard library Str split_delim and the regexp type.
Str.split_delim (Str.regexp " ") "this is my sentence";;
- : bytes list = ["this"; "is"; "my"; "sentence"]
Highly recommend getting UTop, it's really good for quickly searching through Libraries (I typed Str, saw it was there, then Str. and looked for the appropriate function).
The full process goes like this:
first opam install re
if you are using utop, then you can do something like this
#require "re.pcre"
let () =
Re_pcre.split ~rex:(Re_pcre.regexp " +") "Hello world more"
|> List.iter print_endline
and then just run it with utop code.ml
if you want to compile native code, then you'd have:
let () =
Re_pcre.split ~rex:(Re_pcre.regexp " +") "Hello world more"
|> List.iter print_endline
Notice how the #require is gone.
then at command line you'd do: ocamlfind ocamlopt -package re.pcre code.ml -linkpkg -o Test
The OCaml website has tons of tutorials and help, I also have a blog post designed to get you up to speed quickly: http://hyegar.com/2015/10/20/so-youre-learning-ocaml/