How can I use ppx derive (https://github.com/ocaml-ppx/ppx_deriving) in my utop?
For example, I have to following code:
module A = struct
module T = struct
type t = int [##deriving hash, sexp, compare]
end
include Core_kernel.Hashable.Make(T)
end;;
Simply entering:
#require "ppx_jane";;
within utop will make these macros work
Related
I would like to have a few lines of code at the start of my OCaml input file to have toplevel remember the last expression typed all the time, under the name of it. I.e., I want to have:
# 3 + 4;;
val it : int = 7
# it;;
val it : int = 7
# let foo = 42;;
val foo : int = 42
# it + 130;;
val it : int = 137
#
But I don't want to build a custom toplevel or use camlp5 or anything fancy like that.
What I currently do (in OCaml version 4.02.3, I don't know why I have that version; but I hope the exact version doesn't matter?) is the following:
#directory "+compiler-libs";;
#load "/opt/src/ocaml-4.02.3/utils/warnings.cmo";;
#load "/opt/src/ocaml-4.02.3/parsing/location.cmo";;
let convert_phrase x =
match x with
| Parsetree.Ptop_def
[{Parsetree.pstr_desc = Parsetree.Pstr_eval (e, a)}] ->
Parsetree.Ptop_def
([{Parsetree.pstr_desc =
Parsetree.Pstr_value (Asttypes.Nonrecursive,
[{Parsetree.pvb_pat =
{Parsetree.ppat_desc =
Parsetree.Ppat_var (Location.mknoloc "it");
Parsetree.ppat_loc = Location.none;
Parsetree.ppat_attributes = []};
Parsetree.pvb_expr = e;
Parsetree.pvb_attributes = a;
Parsetree.pvb_loc = Location.none}]);
Parsetree.pstr_loc = Location.none}])
| x -> x;;
Toploop.parse_toplevel_phrase :=
let parse_toplevel_phrase = !Toploop.parse_toplevel_phrase in
fun x -> convert_phrase (parse_toplevel_phrase x);;
And that kind of works.
My question: if I just do the #directory "+compiler-libs";; thing, I can access the Toploop and Parsetree modules, but I cannot access the Location module! What is the reason for that? I find having to load .cmo files from my source directories very unattractive.
So is there a way to do what I want without having to have a source tree available?
Or, in other words: why the difference between Toploop and Location, in this respect?
In short, what you should load is not individual .cmo files but
#load "ocamlcommon.cma";;
which is in +compiler-libs directory.
The differences between Parsetree, Toploop and Location are subtle...
In OCaml, data types and their constructors become accessible only with adding its directory to the load path (by #directory "<dir>"). No object code loading (by #load) is required for them.
Parsetree is so called "mli only module": it has only data type definitions and no values are defined. Therefore everything in Parsetree is accessible only by putting it into the load path.
Location defines types and values. Its data types and constructors are accessible without loading the object file but values require the loading. In this case, the object location.cmo is loaded when you load ocamlcommon.cma which archives it.
Toploop is a tricky one. You can access the values of Toploop even without loading toploop.cmo, since Toploop is linked and already available in OCaml toplevel.
I was using QuasiQuotations in Yesod, and everything worked fine. BUT my file became very large and not nice to look at. Also, my TextEditor does not highlight this syntax correctly. That is why is split my files like so:
getHomeR :: Handler Html
getHomeR = do
webSockets chatApp
defaultLayout $ do
$(luciusFile "templates/chat.lucius")
$(juliusFile "templates/chat.julius")
$(hamletFile "templates/chat.hamlet")
If this is wrong, please do tell. Doing runghc myFile.hs throws many errors like this:
chat_new.hs:115:9:
Couldn't match expected type ‘t0 -> Css’
with actual type ‘WidgetT App IO a0’
The lambda expression ‘\ _render_ajFK
-> (shakespeare-2.0.7:Text.Css.CssNoWhitespace . (foldr ($) ...))
...’
has one argument,
but its type ‘WidgetT App IO a0’ has none
In a stmt of a 'do' block:
\ _render_ajFK
...
And this.
chat_new.hs:116:9:
Couldn't match type ‘(url0 -> [(Text, Text)] -> Text)
-> Javascript’
with ‘WidgetT App IO a1’
Expected type: WidgetT App IO a1
Actual type: JavascriptUrl url0
Probable cause: ‘asJavascriptUrl’ is applied to too few arguments
...
And also one for the HTML (Hamlet).
Thus, one per template.
It seems that hamletFile and others treat templates as self-contained, while yours are referencing something from each other. You can play with order of *File calls, or use widgetFile* from Yesod.Default.Util module:
$(widgetFileNoReload def "chat")
The Reload variant is useful for development - it would make yesod devel to watch for file changes and reload them.
I can't find a js_of_ocaml equivalent of document.getElementsByClassName. What is the canonical way to do?
EDIT : I'm using js_of_ocaml v2.5.
It doesn't seem to exist.
The closest I can find to that is by using the className attribute of DOM_html elements (docs) and DOM_svg elements (docs). You can then iterate through the collection and get the element you want.
This was taken from method index which I searched through.
The DOM document class however does have getElementById and getElementBy tag name as shown here.
method getElementById : Js.js_string Js.t -> 'element Js.t Js.opt Js.meth
method getElementsByTagName : Js.js_string Js.t -> 'element nodeList Js.t Js.meth
You can write a function that will call it directly:
let getElementsByClassName (name : Js.js_string Js.t)
: Dom_html.element Dom.nodeList Js.t =
Js.Unsafe.meth_call
Dom_html.document "getElementsByClassName" [|Js.Unsafe.inject name|]
The signature is based on the signature of Dom.document##getElementsByTagName. The type constraints are necessary for type-safe usage.
You can use it like this:
getElementsByClassName (Js.string "control")
You may want to change the interface so it takes an OCaml string, in the style of the Dom_html.getElementById. Then, maybe you should also make it return an OCaml list.
I needed that function too some weeks ago, so I made a PR https://github.com/ocsigen/js_of_ocaml/pull/312
Here is some invalid HStringTemplate syntax:
option_a = $options.a$
option_b = $options.b$
$if options.option_c_is_needed$
option_c = $option.c$
$end$
In other words, part of template file should be created only if specific predicate is true. How can it be achieved via HStringTemplate? If there is no way to do that in it, what libraries could be helpful here?
May be there is some analog of erubis mechanism with ability to use haskell code inside template files?
Hammar's comment is correct. See below:
*Main Text.StringTemplate> render $ setAttribute "optSet" False $ (newSTMP "OptSet: $if(optSet)$Option Is Set$else$Option Isn't Set$endif$" :: StringTemplate String)
"OptSet: Option Isn't Set"
*Main Text.StringTemplate> render $ setAttribute "optSet" True $ (newSTMP "OptSet: $if(optSet)$Option Is Set$else$Option Isn't Set$endif$" :: StringTemplate String)
"OptSet: Option Is Set"
I'm writing a C++ application that needs to interpret and evaluate haskell code. This code isn't known at compile time but given by the user.
Is there a way to use a haskell compiler/interpreter (like GHCi or hugs) as a library?
I found FFI but this seems only to work for haskell code that is known at compile time.
I found the GHC API and hint, but they seem only to work when I want to interpret haskell code from out of haskell.
Instead of using the GHC api I would suggest binding to Hint for this particular approach, which is just a simplified wrapper around the GHC api. The reason I would recommend this is because the GHC api has a bit of a steep learning curve.
But anyway, Like I said In my comment, depending on how deep you want this to go it would require surprisingly few FFI calls. Below I give an example on how to run expressions from a loaded file and return the results (only if there's a show instance). This is just the basics, returning the results as a structure should be possible too.
module FFIInterpreter where
import Language.Haskell.Interpreter
import Data.IORef
import Foreign.StablePtr
type Session = Interpreter ()
type Context = StablePtr (IORef Session)
-- ## Export
-- | Create a new empty Context to be used when calling any functions inside
-- this class.
-- .
-- String: The path to the module to load or the module name
createContext :: ModuleName -> IO Context
createContext name
= do let session = newModule name
_ <- runInterpreter session
liftIO $ newStablePtr =<< newIORef session
newModule :: ModuleName -> Session
newModule name = loadModules [name] >> setTopLevelModules [name]
-- ## Export
-- | free a context up
freeContext :: Context -> IO ()
freeContext = freeStablePtr
-- ## Export = evalExpression
runExpr :: Context -> String -> IO String
runExpr env input
= do env_value <- deRefStablePtr env
tcs_value <- readIORef env_value
result <- runInterpreter (tcs_value >> eval input)
return $ either show id result
Since we have to exit haskell land we have to have some way to refer to the Context, We can do this with a StablePtr and I just wrap it in an IORef to make it mutable in case you want to change things in the future. Note that the GHC API does not support type checking an in-memory buffer, so you have to save the code you want to interpret to a temporary file before loading it.
The -- ## Annotations are for my tool Hs2lib, don't mind them if you don't use it.
My test file is
module Test where
import Control.Monad
import Control.Monad.Instances
-- | This function calculates the value \x->x*x
bar :: Int -> Int
bar = join (*)
and we can test this using a simple test
*FFIInterpreter> session <- createContext "Test"
*FFIInterpreter> runExpr session "bar 5"
"25"
So yeah, it works in Haskell, now to make it work outside of haskell.
Just add to the top of the file a few instructions for Hs2lib on how to marshal ModuleName because that type is defined in a file which it doesn't have the source to.
{- ## INSTANCE ModuleName 0 ## -}
{- ## HS2HS ModuleName CWString ## -}
{- ## IMPORT "Data.IORef" ## -}
{- ## IMPORT "Language.Haskell.Interpreter" ## -}
{- ## HS2C ModuleName "wchar_t*#4" ## -}
or
{- ## HS2C ModuleName "wchar_t*#8" ## -}
if on a 64bit architecture,
and Just invoke Hs2lib
PS Haskell\FFIInterpreter> hs2lib .\FFIInterpreter.hs -n "HsInterpreter"
Linking main.exe ...
Done.
And you'll end up with among others, an Include file with
#ifdef __cplusplus
extern "C" {
#endif
// Runtime control methods
// HsStart :: IO ()
extern CALLTYPE(void) HsStart ( void );
// HsEnd :: IO ()
extern CALLTYPE(void) HsEnd ( void );
// createContext :: ModuleName -> IO (StablePtr (IORef (Interpreter ())))
//
// Create a new empty Context to be used when calling any functionsinside this class.
// String: The path to the module to load or themodule name
//
extern CALLTYPE(void*) createContext (wchar_t* arg1);
// freeContext :: StablePtr (IORef (Interpreter ())) -> IO ()
//
// free a context up
//
extern CALLTYPE(void) freeContext (void* arg1);
// evalExpression :: StablePtr (IORef (Interpreter ())) -> String -> IO String
extern CALLTYPE(wchar_t*) evalExpression (void* arg1, wchar_t* arg2);
#ifdef __cplusplus
}
#endif
I haven't tested the C++ side, but there's no reason it shouldn't work.
This is a very barebones example, if you compile it to a dynamic lib you probably want to redirect stdout, stderr and stdin.
Since GHC is written in Haskell, its API is exclusively available from Haskell. Writing the interfaces you need in Haskell and binding them to C with the FFI, as Daniel Wagner suggested, is going to be the simplest route. This is probably easier than using a direct binding of the GHC API to C would be; you get to use Haskell's strengths to build the interfaces you need, and only interface with them in C++ at the top layer.
Note that Haskell's FFI will only export to C; if you want a C++-ish wrapper around it, you'll have to write it as another layer.
(BTW, Hugs is ancient and unmaintained.)