<html> <head> </head> <body> <div id="test">Foobar</div> <script src="test.js"></script> </body> </html>Now we want to replace the text of the Node with the id
module Main data HTMLElement : Type where Elem : Ptr -> HTMLElement data NodeList : Type where Nodes : Ptr -> NodeList query : String -> IO NodeList query q = do e <- mkForeign (FFun "document.querySelectorAll" [FString] FPtr) q return (Nodes e) item : NodeList -> Int -> IO HTMLElement item (Nodes p) i = do i <- mkForeign (FFun ".item" [FPtr, FInt] FPtr) p i return (Elem i) getId : HTMLElement -> IO String getId (Elem p) = mkForeign (FFun ".id" [FPtr] FString) p setText : HTMLElement -> String -> IO () setText (Elem p) s = mkForeign (FFun ".textContent=" [FPtr, FString] FUnit) p s main : IO () main = do e <- query "#test" i <- item e 0 s <- getId i setText i (s ++ ": SUPERFOO!!!")
Another thing we have to consider is that sometimes we want to refer to a method with no arguments, therefore we have to distinguish them from reading a field. In our example we read the value of the field
id. If we wanted to turn that into a method call we need to declare it like this:
mkForeign (FFun ".id" [FPtr, FUnit] FString) p ()
We simply add an argument of type FUnit to the argument list and apply ().
Operations on arrays are declared like this:
mkForeign (FFun ".id" [FPtr, FInt] FString) mkForeign (FFun ".id=" [FPtr, FInt, FString] FString)
The second argument is treated as an index
One thing that might be worth considering is a way to declare safe foreign calls that do not need to be wrapped in IO.