Propositions vs. boolean values for input validation - idris

I have the following code:
doSomething : (s : String) -> (not (s == "") = True) -> String
doSomething s = ?doSomething
validate : String -> String
validate s = case (not (s == "")) of
False => s
True => doSomething s
After checking the input is not empty I would like to pass it to a function which accepts only validated input (not empty Strings).
As far as I understand the validation is taking place during runtime
but the types are calculated during compile time - thats way it doesn't work. Is there any workaround?
Also while playing with the code I noticed:
:t (("la" == "") == True)
"la" == "" == True : Bool
But
:t (("la" == "") = True)
"la" == "" = True : Type
Why the types are different?

This isn't about runtime vs. compile-time, since you are writing two branches in validate that take care, statically, of both the empty and the non-empty input cases; at runtime you merely choose between the two.
Your problem is Boolean blindness: if you have a value of type Bool, it is just that, a single bit that could have gone either way. This is what == gives you.
= on the other hand is for propositional equality: the only constructor of the type(-as-proposition) a = b is Refl : a = a, so by pattern-matching on a value of type a = b, you learn that a and b are truly equal.
I was able to get your example working by passing the non-equality as a proposition to doSomething:
doSomething : (s : String) -> Not (s = "") -> String
doSomething "" wtf = void $ wtf Refl
doSomething s nonEmpty = ?doSomething
validate : String -> String
validate "" = ""
validate s = doSomething s nonEmpty
where
nonEmpty : Not (s = "")
nonEmpty Refl impossible

As far as I understand the validation is taking place during runtime
but the types are calculated during compile time - thats way it
doesn't work.
That's not correct. It doesn't work because
We need the with form to perform dependent pattern matching, i. e. perform substitution and refinement on the context based on information gained from specific data constructors.
Even if we use with here, not (s == "") isn't anywhere in the context when we do the pattern match, therefore there's nothing to rewrite (in the context), and we can't demonstrate the not (s == "") = True equality later when we'd like to call doSomething.
We can use a wrapper data type here that lets us save a proof that a specific pattern equals the original expression we matched on:
doSomething : (s : String) -> (not (s == "") = True) -> String
doSomething s = ?doSomething
data Inspect : a -> Type where
Match : {A : Type} -> {x : A} -> (y : A) -> x = y -> Inspect x
inspect : {A : Type} -> (x : A) -> Inspect x
inspect x = Match x Refl
validate : String -> String
validate s with (inspect (not (s == "")))
| Match True p = doSomething s p
| Match False p = s

Related

Idris: reconstruct equality after pattern-matching

I'm deconstructing a list into head and tail but later I need a proof that they give me the original list back when combined:
test: Bool -> String
test b = let lst = the (List Nat) ?getListFromOtherFunction in
case lst of
Nil => ""
x :: xs =>
let eq = the ((x::xs) = lst) ?howToDoIt in ""
I'm using Idris 1.3.1.
You can do it with dependent pattern matching:
test: List Nat -> String
test lst with (lst) proof prf
| Nil = ""
| (x :: xs) = ?something
Here prf will hold your equality.
However, I think it's better to simply match on lst in the LHS, then your proofs will auto-simplify where needed.

Idris - proving equality of two numbers

I would like to write a function that takes two natural arguments and returns a maybe of a proof of their equality.
I'm trying with
equal : (a: Nat) -> (b: Nat) -> Maybe ((a == b) = True)
equal a b = case (a == b) of
True => Just Refl
False => Nothing
but I get the following error
When checking argument x to constructor Prelude.Maybe.Just:
Type mismatch between
True = True (Type of Refl)
and
Prelude.Nat.Nat implementation of Prelude.Interfaces.Eq, method == a
b =
True (Expected type)
Specifically:
Type mismatch between
True
and
Prelude.Nat.Nat implementation of Prelude.Interfaces.Eq, method == a
b
Which is the correct way to do this?
Moreover, as a bonus question, if I do
equal : (a: Nat) -> (b: Nat) -> Maybe ((a == b) = True)
equal a b = case (a == b) of
True => proof search
False => Nothing
I get
INTERNAL ERROR: Proof done, nothing to run tactic on: Solve
pat {a_504} : Prelude.Nat.Nat. pat {b_505} : Prelude.Nat.Nat. Prelude.Maybe.Nothing (= Prelude.Bool.Bool Prelude.Bool.Bool (Prelude.Interfaces.Prelude.Nat.Nat implementation of Prelude.Interfaces.Eq, method == {a_504} {b_505}) Prelude.Bool.True)
This is probably a bug, or a missing error message.
Please consider reporting at https://github.com/idris-lang/Idris-dev/issues
Is it a known issue or should I report it?
Let's take a look at the implementation of the Eq interface for Nat:
Eq Nat where
Z == Z = True
(S l) == (S r) = l == r
_ == _ = False
You can solve the problem just by following the structure of the (==) function as follows:
total
equal : (a: Nat) -> (b: Nat) -> Maybe ((a == b) = True)
equal Z Z = Just Refl
equal (S l) (S r) = equal l r
equal _ _ = Nothing
You can do it by using with instead of case (dependent pattern matching):
equal : (a: Nat) -> (b: Nat) -> Maybe ((a == b) = True)
equal a b with (a == b)
| True = Just Refl
| False = Nothing
Note that, as Anton points out, this merely a witness on a boolean test result, a weaker claim than proper equality. It might be useful for advancing a proof about if a==b then ..., but it won't allow you to substitute a for b.

How to Compare Types for Equality?

I attempted to compare a String and String, expecting True.
Idris> String == String
Can't find implementation for Eq Type
Then I expected False when comparing a String to a Bool.
Idris> String /= Bool
Can't find implementation for Eq Type
Am I missing an import?
You can't as it would break parametricity, which we have in Idris. We can't pattern match on types. But this would be necessary to write the Eq implementation, for example:
{- Doesn't work!
eqNat : Type -> Bool
eqNat Nat = True
eqNat _ = False -}
Also, if one could pattern match on types, they would be needed in the run-time. Right now types get erased when compiling.
Just to add some simple examples to the above: types can't be pattern matched on, but there's a two parameter type constructor for propositional equality, described in the documentation section on Theorem Proving. Notice that the only constructor, Refl, makes only values of type (=) x x, where both type parameters are the same. (this is ≡ in Agda)
So this will typecheck:
twoPlusTwoEqFour : 2 + 2 = 4
twoPlusTwoEqFour = Refl
so will this:
stringEqString : String = String
stringEqString = Refl
but not this:
stringEqInt : String = Int
stringEqInt = Refl
-- type error: Type mismatch between String and Int
and this needs extra work to prove, because addition is defined by recursion on the left argument, and n + 0 can't be reduced further:
proof : n = n + 0

SML converting a string to an int with error catching

So what I want to do is to convert a string into an int and do some error catching on it. I would also like to know where I would put what I want it to do after it fails if it does.
I know how to convert, but I am not sure how to catch it and where the code will jump to after the error
I believe the method for converting it Int.fromString(x)
Thank you.
SML has two approaches to error handling. One, based on raise to raise errors and handle to catch the error, is somewhat similar to how error handling works in languages like Python or Java. It is effective, but the resulting code tends to lose some of its functional flavor. The other method is based on the notion of options. Since the return type of Int.fromString is
string -> int option
it makes the most sense to use the option-based approach.
An int option is either SOME n, where n is and integer, or it is NONE. The function Int.fromString returns the latter if it fails in its attempt to convert the string to an integer. The function which calls Int.fromString can explicitly test for NONE and use the valOf to extract the value in the case that the return value is of the form SOME n. Alternatively, and somewhat more idiomatically, you can use pattern matching in a case expression. Here is a toy example:
fun squareString s =
case Int.fromString(s) of
SOME n => Int.toString (n * n) |
NONE => s ^ " isn't an integer";
This function has type string -> string. Typical output:
- squareString "4";
val it = "16" : string
- squareString "Bob";
val it = "Bob isn't an integer" : string
Note that the clause which starts NONE => is basically an error handler. If the function that you are defining isn't able to handle such errors, it could pass the buck. For example:
fun squareString s =
case Int.fromString(s) of
SOME n => SOME (Int.toString (n * n))|
NONE => NONE;
This has type string -> string option with output now looking like:
- squareString "4";
val it = SOME "16" : string option
- squareString "Bob";
val it = NONE : string option
This would make it the responsibility of the caller to figure out what to do with the option.
The approach to error handling that John explains is elaborated in the StackOverflow question 'Unpacking' the data in an SML DataType without a case statement. The use-case there is a bit different, since it also involves syntax trees, but the same convenience applies for smaller cases:
fun squareString s = Int.fromString s >>= (fn i => SOME (i*i))
Assuming you defined the >>= operator as:
infix 3 >>=
fun NONE >>= _ = NONE
| (SOME a) >>= f = f a
The drawback of using 'a option for error handling is that you have to take into account, every single time you use a function that has this return type, whether it errored. This is not unreasonable. It's like mandatory null-checking. But it comes at the cost of not being able to easily compose your functions (using e.g. the o operator) and a lot of nested case-ofs:
fun inputSqrt s =
case TextIO.inputLine TextIO.stdIn of
NONE => NONE
| SOME s => case Real.fromString s of
NONE => NONE
| SOME x => SOME (Math.sqrt x) handle Domain => NONE
A workaround is that you can build this constant error handling into your function composition operator, as long as all your functions share the same way of expressing errors, e.g. using 'a option:
fun safeSqrt x = SOME (Math.sqrt x) handle Domain => NONE
fun inputSqrt () =
TextIO.inputLine TextIO.stdIn >>=
(fn s => Real.fromString s >>=
(fn x => safeSqrt x))
Or even shorter by applying Eta conversion:
fun inputSqrt () = TextIO.inputLine TextIO.stdIn >>= Real.fromString >>= safeSqrt
This function could fail either because of a lack of input, or because the input didn't convert to a real, or because it was negative. Naturally, this error handling isn't smart enough to say what the error was, so you might want to extend your functions from using an 'a option to using an ('a, 'b) either:
datatype ('a, 'b) either = Left of 'a | Right of 'b
infix 3 >>=
fun (Left msg) >>= _ = Left msg
| (Right a) >>= f = f a
fun try (SOME x) _ = Right x
| try NONE msg = Left msg
fun inputLine () =
try (TextIO.inputLine TextIO.stdIn) "Could not read from stdIn."
fun realFromString s =
try (Real.fromString s) "Could not derive real from string."
fun safeSqrt x =
try (SOME (Math.sqrt x) handle Domain => NONE) "Square root of negative number"
fun inputSqrt () =
inputLine () >>= realFromString >>= safeSqrt
And trying this out:
- ​inputSqrt ();
​9
> val it = Right 3.0 : (string, real) either
- ​inputSqrt ();
​~42
> val it = Left "Square root of negative number" : (string, real) either
- ​inputSqrt ();
Hello
> val it = Left "Could not derive real from string." : (string, real) either
- (TextIO.closeIn TextIO.stdIn; inputSqrt ());
> val it = Left "Could not read from stdIn." : (string, real) either

Is there an F# equivalent to this C# extension method?

I find the following C# extension method very useful:
public static bool In<T>(this T x, params T[] xs)
{
return xs.Contains(x);
}
allowing for C# calls such as
var s = "something else";
var rslt = s.In("this","that","other") ? "Yay" : "Boo";
and
var i = 1;
var rslt = i.In(1,2,3) ? "Yay" : "Boo";
I have been trying to come up with an F# (near-)equivalent, allowing e.g.:
let s = "something else"
let rslt = if s.In("this","that","other") then "Yay" else "Boo"
It seems like I would need something like:
type 'T with
static member this.In([ParamArray] xs : 'T )
{
return xs.Contains(x);
}
but that is not legal F# syntax. I can't see how to declare a extension method on a generic class in F#. Is it possible? Or is there a better way to achieve similar results? (I imagine I could just link in the C# project and call it from F#, but that would be cheating! :-)
The best I could come up with was:
let inline In (x : 'a, [<ParamArray>] xs : 'a[]) = Array.Exists( xs, (fun y -> x = y) )
which I expected to allow for calls like (which are not really acceptable anyway imho):
if In(ch, '?', '/') then "Yay" else "Boo"
but in fact required:
if In(ch, [| '?'; '/' |]) then "Yay" else "Boo"
implying that the ParamArray attribute is being ignored (for reasons I've yet to fathom).
Fwiw, the latest version of F# (3.1) contains exactly what I was after (yay!):
[<Extension>]
type ExtraCSharpStyleExtensionMethodsInFSharp () =
[<Extension>]
static member inline In(x: 'T, xs: seq<'T>) = xs |> Seq.exists (fun o -> o = x)
[<Extension>]
static member inline Contains(xs: seq<'T>, x: 'T) = xs |> Seq.exists (fun o -> o = x)
[<Extension>]
static member inline NotIn(x: 'T, xs: seq<'T>) = xs |> Seq.forall (fun o -> o <> x)
providing usages as
if s.In(["this","that","other"]) then ....
if (["this","that","other"]).Contains(s) then ...
etc.