Query the SML/NJ REPL for signatures or structures? - sml

Is there a way to get a list of the signatures or structures available in the top-level environment from the SML/NJ REPL? I'm looking to get a listing of the signatures/structures that appear to be defined in the sources.cm files in the sml source directory. Something along the lines of
- signature s = LIST;
only listing the bindings in the top-level environment instead.

You can make use of the internal structures that SML/NJ provides:
fun boundSignatures () =
let
fun isSignature symbol = Symbol.nameSpace symbol = Symbol.SIGspace
val signatures = List.filter isSignature (EnvRef.listBoundSymbols ())
in
List.app (fn s => print (Symbol.name s ^ "\n")) signatures
end
Please note that, due to autoloading, EnvRef.listBoundSymbols won't return symbol names for modules which are available, but haven't yet been loaded:
- boundSignatures ();
ENVREF
val it = () : unit
- signature S = STATICENV;
[autoloading]
[autoloading done]
- boundSignatures ();
STATICENV
ENVREF
S
val it = () : unit

Related

ML: Is it possible to create a list of structures in SML?

I am a beginner to ML/Haskell and I am trying to create a list of structures.
Actually, I am developing a web application in Urweb (functional web programming language, a lot of features from ML and Haskell.) I am trying to create an interface to Tinymce (open source rich text editor, and it consists of all the plugin such as print, link). So to manage all plugins, I am composing in the form of structure and I need one data structure to hold all the structures (Plugins in my case) and at the end stage in can be used to initialize my editor.
For example:
val plugins = [print, link, img];
and elements inside list plugins such as print is a structure:
structure print = struct
type t = string
.
.
end
How can I achieve this?
The general answer is that No you cannot create a list of
structures, the same is true as well of signatures, and functors
however; if your plugin system is built in a way in which the entry types, and exit types of each plugin are the same across all plugins, you can build a kind of closure to a structure and embed that into a function.
you can then use functors, to build up the functions of your plugin system
We start out with the interface of each "plugin".
signature DANCER =
sig
type t;
val dancer : t
val tired : t -> bool
val dance : t -> t;
end
Followed by the interface through which our application interacts with the plugin.
datatype exhaustion = Exhausted;
signature DANCING_MANIA =
sig
val dance : unit -> exhaustion;
end
The implementation of the above DANCING_MANIA signature,
accepts a DANCER, and hides the differences between plugins/structures
functor Dancer (D : DANCER) : DANCING_MANIA =
struct
fun dance() =
let fun until_exhaustion (dancer) =
if not (D.tired dancer)
then until_exhaustion(D.dance(dancer))
else Exhausted;
in until_exhaustion(D.dancer) end
end
Finally we can implement some plugins, and throw them in a list.
structure Tony :> DANCER =
struct
type t = int;
val dancer = 5;
fun tired x = x <= 0;
fun dance x = (print "tony dance!\n"; x - 1);
end
structure Annette :> DANCER =
struct
type t = real;
val dancer = 1.0;
fun tired x = x <= 0.0;
fun dance x = (print "annette dance!\n"; x - 0.2);
end
structure TonyDance = Dancer(Tony);
structure AnnetteDance = Dancer(Annette);
val dancers = [TonyDance.dance, AnnetteDance.dance];
fun danceOff (x::xs) = let val _ = x(); in danceOff(xs) end
| danceOff ([]) = ();
val _ = danceOff(dancers);
So, the idea is that while you cannot create a list of structures,
you can create a list of things, that each contain a different structure,
as long as the exposed types are uniform.

Inserting a regexp() SQLite function in Haskell (Database.SQLite3,"direct-sqlite")

I need to create an implementation of the regex() SQLite function in a Haskell database connection so that I can use the "REGEX" operator in queries.
Now, I have an implementation of a regex matching function that uses PCRE:
import Text.Regex.Base.RegexLike
import qualified Text.Regex.PCRE.ByteString as PCRE
import qualified Data.ByteString as BS
sqlRegex :: BS.ByteString -> BS.ByteString -> IO Bool
sqlRegex reg b = do
reC <- pcreCompile reg
re <- case reC of
(Right r) -> return r
reE <- PCRE.execute re b
case reE of
(Right (Just _)) -> return True
(Right (Nothing)) -> return False
where pcreCompile = PCRE.compile defaultCompOpt defaultExecOpt
which works well (please excuse the very explicit calls)
> sqlRegex (Data.ByteString.Char8.pack ".*") (Data.ByteString.Char8.pack "hello")
True
> sqlRegex (Data.ByteString.Char8.pack "H.*") (Data.ByteString.Char8.pack "hello")
False
Now, how do I create the SQLite function??
conn <- open $ pack dbFile
createFunction conn "regexp" (Just 2) True [..... and what should go here?]
The docs for createFunction
helps me as far as making me understand that I need to make the function take a context and some arguments, but the refs for those data does not help me at all!
How should make my function take a FuncContext and FuncArgs??
There is an example in the github repo:
https://github.com/IreneKnapp/direct-sqlite/blob/master/test/Main.hs#L743-757
-- implements repeat(n,str)
repeatString ctx args = do
n <- funcArgInt64 args 0
s <- funcArgText args 1
funcResultText ctx $ T.concat $ replicate (fromIntegral n) s
You use the functions funcArg... to get the arguments and functions like funcResult... to return them.
Links to the docs:
Extract Function Arguments
Set the Result of a Function

Common Parse error: "in" in a function that call other functions OCaml

Well this Parse error: "in" expected after [binding] (in [expr])
is a common error as far I have searched in Ocaml users, but in the examples I saw I didnt found the answer for my error, then I will explain my problem:
I declared this function:
let rec unit_propag xs =
let cuAux = teste xs
let updatelist = funfilter (List.hd(List.hd cuAux)) (xs)
let updatelist2 = filtraelem (negar(List.hd(List.hd cuAux))) (updatelist)
if(not(List.mem [] xs) && (teste xs <> []))
then
unit_propag updatelist2
;;
The functions I am using inside this code were declared before like this:
let funfilter elem xs = List.filter (fun inner -> not (List.mem elem inner)) xs;;
let filtraele elem l = List.map( fun y -> List.filter (fun x -> x <> elem) y)l;;
let teste xs = List.filter(fun inner ->(is_single inner)inner)xs;;
let is_single xs = function
|[_] -> true
|_ -> false
;;
let negar l =
match l with
V x -> N x
|N x -> V x
|B -> T
|T -> B
;;
But not by this order.
Well they were all doing what I wanted to do, but now when I declared unit_propag and tried to compile, I had an error in line of
let cuAux = teste xs
It said:
File "exc.ml", line 251, characters 20-22:
Parse error: "in" expected after [binding] (in [expr])
Error while running external preprocessor
Command line: camlp4o 'exc.ml' > /tmp/ocamlpp5a7c3d
Then I tried to add a ; on the end of each function, and then my "in" error appeared on the line of the last function, is this case unit_propag updatelist2
What I am doing wrong? people usually say that this kind of errors occurs before that code, but when i comment this function the program compiles perfectly.
I need to post more of my code? Or i need to be more clear in my question?
Is that possible to do in Ocaml or I am doing something that I cant?
Thanks
The error message says you're missing in, so it seems strange to solve it by adding ; :-)
Anyway, you're missing the keyword in after all the let keywords in your function unit_propag.
You should write it like this:
let rec unit_propag xs =
let cuAux = teste xs in
let updatelist = funfilter (List.hd(List.hd cuAux)) (xs) in
let updatelist2 =
filtraelem (negar(List.hd(List.hd cuAux))) (updatelist)
in
if (not (List.mem [] xs) && (teste xs <> [])) then
unit_propag updatelist2
The basic issue has been explained many times here (as you note). Basically there are two uses of the keyword let. At the outer level it defines the values in a module. Inside another definition it defines a local variable and must be followed by in. These three lets are inside the definition of unit_propag.
Another attempt to explain the use of let is here: OCaml: Call function within another function.

What do questions marks mean in Standard ML types?

For instance:
vagrant#precise32:/vagrant$ rlwrap sml
Standard ML of New Jersey v110.76 [built: Mon May 12 17:11:57 2014]
- TextIO.StreamIO.inputLine ;
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val it = fn : ?.TextIO.instream -> (string * ?.TextIO.instream) option
- val s = TextIO.openIn "README.md" ;
val s = - : TextIO.instream
- TextIO.StreamIO.inputLine s ;
stdIn:3.1-3.28 Error: operator and operand don't agree [tycon mismatch]
operator domain: ?.TextIO.instream
operand: TextIO.instream
in expression:
TextIO.StreamIO.inputLine s
-
I know that dummy type variables created due to the value restriction will have question marks in them, e.g.
- [] # [];
stdIn:17.1-17.8 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val it = [] : ?.X1 list
... but this doesn't apply to the example above as the value restriction isn't involved.
In these lecture notes, I found the following comment, on page 23:
In fact, as indicated by the question marks ? in the error
message, it now has a type that cannot even be named anymore,
since the new but identically named definition of mylist shadows
it.
But this is referring to a type checking error, and anyway my example with TextIO.StreamIO this shouldn't apply as nothing is being shadowed.
edited to add
So I figured out my actual problem, which was how to get a ?.TextIO.instream from a filename, but I still don't really know what the question marks are about:
vagrant#precise32:/vagrant$ rlwrap sml
Standard ML of New Jersey v110.76 [built: Mon May 12 17:11:57 2014]
val fromFile : string -> TextIO.StreamIO.instream =
= TextIO.getInstream o TextIO.openIn ;
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val fromFile = fn : string -> ?.TextIO.instream
- TextIO.getInstream ;
val it = fn : TextIO.instream -> ?.TextIO.instream
- TextIO.StreamIO.input1 (fromFile "README.md") ;
val it = SOME (#"#",-) : (TextIO.StreamIO.elem * ?.TextIO.instream) option
-
second edit
I discovered that Poly/ML doesn't use these question marks when printing types, so I assume this is something specific to SML/NJ:
Poly/ML 5.5.1 Release
> TextIO.StreamIO.inputLine ;
val it = fn:
TextIO.StreamIO.instream -> (string * TextIO.StreamIO.instream) option
> val fromFile : string -> TextIO.StreamIO.instream =
TextIO.getInstream o TextIO.openIn ;
# val fromFile = fn: string -> TextIO.StreamIO.instream
> TextIO.getInstream ;
val it = fn: TextIO.instream -> TextIO.StreamIO.instream
>
I'd still be curious if anyone knows under what circumstances SML/NJ prints these questions marks and what the story is behind them...
I believe this is specific to SML/NJ, and they are used when printing a type that does not have an accessible name (or probably, when the name that SML/NJ comes up with it is not accessible, since SML/NJ seems to just use some heuristic for printing types at the REPL). The value restriction is one way that such types arise (here SML/NJ chooses to unfiy the type with some useless new type). Here's another simple interaction that demonstrates another way, when the only name for a type (S.t) is shadowed by a new declaration of S:
- structure S = struct datatype t = X end;
structure S :
sig
datatype t = X
end
- val y = S.X;
val y = X : S.t
- structure S = struct end;
structure S : sig end
- y;
val it = X : ?.S.t
I think that in your example, there are multiple substructures called TextIO in the basis, and the toplevel TextIO structure is probably shadowing the one you're accessing. SML/NJ may also just be choosing a bad name for the type and not realizing that there's a sharing declaration or something that makes it possible to write the type down.

Linear types in OCaml

Rust has a linear type system. Is there any (good) way to simulate this in OCaml? E.g., when using ocaml-lua, I want to make sure some functions are called only when Lua is in a specific state (table on top of stack, etc).
Edit: Here's a recent paper about resource polymorphism relevant to the question: https://arxiv.org/abs/1803.02796
Edit 2: There are also a number of articles about session types in OCaml available, including syntax extensions to provide some syntactic sugar.
As suggested by John Rivers, you can use a monadic style to represent
"effectful" computation in a way that hides the linear constraint in
the effect API. Below is one example where a type ('a, 'st) t is
used to represent computation using a file handle (whose identity is
implicit/unspoken to guarantee that it cannot be duplicated), will
product a result of type 'a and leave the file handle in the state
'st (a phantom type being either "open" or "close"). You have to use
the run of the monad¹ to actually do anything, and its type ensure
that the file handles are correctly closed after use.
module File : sig
type ('a, 'st) t
type open_st = Open
type close_st = Close
val bind : ('a, 's1) t -> ('a -> ('b, 's2) t) -> ('b, 's2) t
val open_ : string -> (unit, open_st) t
val read : (string, open_st) t
val close : (unit, close_st) t
val run : ('a, close_st) t -> 'a
end = struct
type ('a, 'st) t = unit -> 'a
type open_st = Open
type close_st = Close
let run m = m ()
let bind m f = fun () ->
let x = run m in
run (f x)
let close = fun () ->
print_endline "[lib] close"
let read = fun () ->
let result = "toto" in
print_endline ("[lib] read " ^ result);
result
let open_ path = fun () ->
print_endline ("[lib] open " ^ path)
end
let test =
let open File in
let (>>=) = bind in
run begin
open_ "/tmp/foo" >>= fun () ->
read >>= fun content ->
print_endline ("[user] read " ^ content);
close
end
(* starting with OCaml 4.13, you can use binding operators:
( let* ) instead of ( >>= ) *)
let test =
let open File in
let ( let* ) = bind in
run begin
let* () = open_ "/tmp/foo" in
let* content = read in
print_endline ("[user] read " ^ content);
close
end
Of course, this is only meant to give you a taste of the style of
API. For more serious uses, see Oleg's monadic
regions examples.
You may also be interested in the research programming language
Mezzo, which aims to
be a variant of ML with finer-grained control of state (and related
effectful patterns) through a linear typing discipline with separated
resources. Note that it is only a research experiment for now, not
actually aimed at users. ATS is also relevant,
though finally less ML-like. Rust may actually be a reasonable
"practical" counterpart to these experiments.
¹: it is actually not a monad because it has no return/unit combinator, but the point is to force type-controlled sequencing as the monadic bind operator does. It could have a map, though.