PureScript equivalent to ‘error’ from Haskell prelude - assertion

I’m new to PureScript and trying to find the idiom for “assertion failure”. I use this commonly to halt execution when:
an invariant I need to rely on is broken
a branch of the code is unreachable
I want to defer the implementation of an expression but want that to “fail fast” at runtime (rather than just yield undefined)
In Haskell I would typically use the prelude function error for this kind of thing. In PureScript, I (naively) expected to be able to emulate error by throwing an exception and (unsafely) casting away the effect type, as below:
module Test.Test where
import Prelude
import Effect (Effect)
import Effect.Exception (throw)
import Unsafe.Coerce (unsafeCoerce)
main :: Effect Unit
main = do
_ <- pure $ error "Doesn't fail"
error' "Fails"
error :: ∀ a . String -> a
error = unsafeCoerce <<< throw
error' :: ∀ a . String -> Effect a
error' = throw
But this doesn't work: if I embed calls to error inside a large program, I end up with runtime objects with fields which are undefined (in the JavaScript sense), rather than a program which terminates abruptly as soon as error is executed. The function throw seems to do what I want, but it doesn't seem appropriate to pollute my program with the Effect type for the use cases above.
I don't object to PureScript's behaviour -- it seems reasonable that I can't cast an effectful computation to a pure one and still observe the effects. So I guess I'm missing a trick (or a library function that I haven't found yet). What's the PureScript idiom for what I'm looking for?
(The testing library purescript-assert provides assert functionality, but it too has type Effect Unit.)

What you need is unsafePerformEffect - it will execute the effect in a transparent way and return its result as a pure value.
error :: forall a. String -> a
error = unsafePerformEffect <<< throw
Or, alternatively, it's very easy to FFI your own:
-- PureScript
foreign import error :: String -> a
// JS (foreign module)
exports.error = msg => throw new Error(msg)

Related

Conversion from ocaml to rescript "Did you forget a `=>` here?" syntax error

Trying to convert this OCaml code to Rescript
let emptyEventHandler = ((((fun _ev -> ())
[#bs ]) : Web.Node.event_cb) : Web.Node.event_cb)
And that is what I have got after the conversion
let emptyEventHandler: Web.Node.event_cb = ((. _ev) => (): Web.Node.event_cb)
the error is Did you forget a `=>` here? (at the end)
Does anyone know if this is caused by the syntax changes they made on Rescript and any idea on how can this be fixed?
The original OCaml has a duplicate type annotation for some reason. This is valid in OCaml because everything is an expression, and every expression can have a type annotation, but is completely redundant. One possible reason for this happening is that the code might have been converted between OCaml and Reason too many times.
Rescript doesn't seem to support this case. It prefers type annotations on bindings and doesn't seem to support type annotations on expressions in general. But since Rescript is still represented by OCaml's AST, which does not make this distinction, it seems it will only take the first type annotation of a binding expression leaving the rest as-is and producing invalid Rescript code.
I'd consider this a bug since I think it should produce an error instead of invalid code, but either way the fix is simple, just remove the extraneous type annotation.
In OCaml it would then become:
let emptyEventHandler = (((fun _ev -> ()) [#bs]) : Web.Node.event_cb)
And in Rescript:
let emptyEventHandler: Web.Node.event_cb = (. _ev) => ()

How to print file location of calling function in OCaml?

I'm trying to make a custom assert function with greater functionality, except the problem is the assert exception points to inside the custom assert function, which isn't useful for the end user when they're trying to figure out which assertion failed.
Here's what I have so far:
let assert_eq (exp: 'a) (exp2: 'a) =
assert (exp = exp2)
OCaml doesn't have an interface for a function to determine details of its call site. The reason it's possible for the built-in assert mechanism is just that: it's a built-in mechanism, not an ordinary function call.
There is a way to determine the current function, filename, line number, and module. In the documentation for Stdlib (in a section named Debugging) you'll find __FUNCTION_, __FILE__, __LINE__, and __MODULE__. There are a few more similar names that capture various combinations. The documentation for Stdlib is here: https://v2.ocaml.org/releases/4.14/api/Stdlib.html
To create an assert function that can access these values from the call site I'm pretty sure you'll need to create a syntax extension that passes them along. The currently favored mechanism for doing this is PPX. The best general description I could find of PPX is here: https://ocaml-ppx.github.io/ppxlib/ppxlib/manual.html#what-is-ppx
In sum, I'd say this is a project that requires advanced features of OCaml.

How do I write a scala unit test that ensures compliation fails?

Is there any way to write something like a "unit test" which makes sure some code does not compile?
Why would I want such a thing? Two reasons.
1) Check the type safety of my API. I'd like a way to make sure if someone passes in a bad value, you get a compiler error, not just a runtime error. Obviously, I can just run the compiler and check for the error, but having it formalized in a unit test is good for avoiding a regression & also for documentation.
Eg., consider this test. There is some commented out code which I had used to check type-safety:
https://github.com/squito/boxwood/blob/master/core/src/test/scala/com/quantifind/boxwood/EnumUnionTest.scala#L42
(lines 42 & 48 -- on line 34 I call a different API which has a runtime exception, which I can check)
It actually took me a while to get the type-safety right, so those were important checks. Now if I go and modify the underlying implementation, I can't just run my test suite -- I've got to also remember to uncomment those lines and check for a compiler error.
2) Testing error handling of macros. If a macro has some bad input, it should result in a compiler error. Same issues here, same desire to have it in a easy-to-run test-suite.
I use ScalaTest, but I'm happy to here a solution with any unit-testing framework.
As I note in a comment above, Shapeless 2.0 (not yet released but currently available as a milestone) has a very nice implementation of the functionality you're looking for, based on a solution by Stefan Zeiger. I've added a demo to your project here (note that I've had to update to Scala 2.10, since this solution uses a macro). It works like this:
import shapeless.test.illTyped
//this version won't even compile
illTyped("getIdx(C.Ooga)")
//We can have multiple enum unions exist side by side
import Union_B_C._
B.values().foreach {b => Union_B_C.getIdx(b) should be (b.ordinal())}
C.values().foreach {c => Union_B_C.getIdx(c) should be (c.ordinal() + 2)}
//Though A exists in some union type, Union_B_C still doesn't know about it,
// so this won't compile
illTyped("""
A.values().foreach {a => Union_B_C.getIdx(a) should be (a.ordinal())}
""")
If we were to change the code in the second call to illTyped to something that will compile:
B.values().foreach {a => Union_B_C.getIdx(a) should be (a.ordinal())}
We'd get the following compilation error:
[error] .../EnumUnionTest.scala:56: Type-checking succeeded unexpectedly.
[error] Expected some error.
[error] illTyped("""
[error] ^
[error] one error found
[error] (core/test:compile) Compilation failed
If you'd prefer a failed test, you could pretty easily adapt the implementation in Shapeless. See Miles's answer to my previous question for some addition discussion.
Scalatest can also do this.
Checking that a snippet of code does not compile
Often when creating libraries you may wish to ensure that certain
arrangements of code that represent potential “user errors” do not
compile, so that your library is more error resistant. ScalaTest
Matchers trait includes the following syntax for that purpose:
"val a: String = 1" shouldNot compile
If you want to ensure that a
snippet of code does not compile because of a type error (as opposed
to a syntax error), use:
"val a: String = 1" shouldNot typeCheck
Note that the shouldNot typeCheck syntax will only succeed if the given snippet of code does
not compile because of a type error. A syntax error will still result
on a thrown TestFailedException.
If you want to state that a snippet of code does compile, you can make
that more obvious with:
"val a: Int = 1" should compile
Although the previous three constructs
are implemented with macros that determine at compile time whether the
snippet of code represented by the string does or does not compile,
errors are reported as test failures at runtime.
Travis Brown's answer is absolutely correct. Just in the interest of completeness, I want to add that this also works for testing macros, as demonstrated here.
One minor point: the illTyped check doesn't seem to work in the repl. It never throws an error, even if the given expression does type check. But don't let that fool you, it does work well.
> test:console
Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_65).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def foo(s: String) = s
foo: (s: String)String
scala> import shapeless.test.illTyped
import shapeless.test.illTyped
scala> foo(1)
<console>:10: error: type mismatch;
found : Int(1)
required: String
foo(1)
^
scala> illTyped("""foo(1)""")
scala> illTyped("""foo("hi there")""") // <--- works, but shouldn't!

Python/SWIG TypeError

I've created a simple SWIG helper function to deal with the pointers returned from the C++ code I've wrapped:
//in module foo:
%inline %{
double getPtrVal(double *ptr, int i) {
return (double) ptr[i];
}
%}
This worked fine until I tried something like:
for i in range(n):
for j in range(n):
val = foo.getPtrVal(ptrs, i)
at which point Python returned with a TypeError, complaining that n wasn't an integer:
for i in range(n):
TypeError: an integer is required
I assure you that n is, in fact, an integer (type(n) consistently returns <type 'int'>). Thus, I believe the problem lies somehow in the SWIG function. The strange thing is that foo.getPtrVal(ptrs, i) is called n times without issue, then, immediately after exiting the inner loop over j for the first time, the error is thrown. Any ideas? I could post further code segments if it would clarify parts. Thanks!
I've run into a similar problem before. If some part of your SWIG C wrapper code is not properly cleaning up Python's internal exception state, then the very next builtin call capable of raising an exception in your Python code will appear to be the source of the exception.
range can raise exceptions, so Python inspects its internal exception state after calling it, sees the exception left over from your SWIG C wrapper code, and assumes that it must have come from range.
When I couldn't fix such a problem I used this ugly workaround to clear the internal exception state:
try:
sys.stdout.write("") # any call capable of raising an exception will do
except:
pass
The proper way might be with an %exception directive; see the SWIG manual. But you need to figure out which call is causing the exception, first.
Did actual code have missing colon?

the reasons of errors in ML code

The below code is just a kind of prototype. What I want to know is why it fails to compile.
fun test(list) =
let
fun inner(list) =
let
val from = #1(hd(list))
in
if null(tl(list)) = false then innerinner(tl(list),from)
else false
end
fun innerinner(list,from) =
if #2(hd(list)) = from then true
else if null(list) = false then innerinner(tl(list),from)
else false
in
inner(list)
end;
The error messages are:
test.txt:7.34-7.44 Error: unbound variable or constructor: innerinner
test.txt:3.2-9.6 Error: unresolved flex record
(can't tell what fields there are besides #1)
test.txt:10.2-13.13 Error: unresolved flex record
(can't tell what fields there are besides #2)
uncaught exception Error
raised at: ../compiler/Toplevel/interact/evalloop.sml:66.19-66.27
....
I am a kind beginner of ML programming. Could anyone teach me what is wrong?
You have quite a few things going on here. If we first look at the errors you are getting.
unbound variable or constructor: innerinner
In sml you can't "use" stuff before it has been declared. It is easily fixed in your case by
swapping the function declarations around, and thus declaring innerinner before inner.
If you ever end up in a case where you want to for example declare two mutually recursive
functions, then this is not an option. In this case you would have to use the keyword and.
unresolved flex record
This is a bit more complicated. It is a type error and has something to do with the fact
that tuples are represented as records internally (I would recommend you go read about
it). Thus when you don't supply enough information, the type system will complain.
I think this QA explains it quite good. In summary, you can't have unbounded tuples
and thus you need to make it clear to the type system how many elements it contains. This
could be done by explicitly type annotating the function declaration.
However in general you ought to use pattern matching instead, as often as feasible.
In general you should always use pattern matching rather than tuple selectors (#1, #2, ...), or list selectors (hd or tl). You just saw why tuple selectors can be "bad" but using list selectors without testing whether or not the list is empty first will give you runtime errors (exceptions).
Putting in such test cases in your code will "blow it up" and make it messy to read. But if you use pattern matching instead you will have some nice clear cut cases in your function definition.
Also often you will tend to writer less code (in my opinion).
Btw, you don't need to put parentheses around single arguments to functions, such as you main definition of the test function.
All in all your function could look something like this:
fun test list =
let
fun innerinner ((x1, x2)::xs,from) =
if x1 = from then true
else innerinner(xs,from)
| innerinner ([], from) = false
fun inner ((x1, x2)::xs) = innerinner(xs,x1)
| inner [] = false
in
inner(list)
end