returning a function returning bool VS returning bool (OCaml) - function

type form = TRUE
|FALSE
|NOT of form
let rec check x = function
TRUE -> true
|FALSE -> false
|NOT(y) -> not eval y
(*where TRUE, FALSE and NOT all custom type 'form'*)
I tried to define a function form -> bool, but I got an compile error for
|NOT(y) -> not eval y
line. The error message says
This expression type form -> bool, but an expression was expected of type bool
though the function 'eval' returns type 'bool', what's the reason it can't be a return value for a function returning bool?

The type of the function you defined (check or eval) is 'a -> form -> bool. You match against implicit input parameter introduced by function keyword. First parameter x is not used (but expected).
As eval has two input parameters, (eval y) expression has type form -> bool. This is what the error message about.
Try this:
let rec eval = function
| TRUE -> true
| FALSE -> false
| NOT(y) -> not (eval y)
Alternative form with explicit input parameter x:
let rec eval x = match x with
| TRUE -> true
| FALSE -> false
| NOT(y) -> not (eval y)

Related

OCaml 5.0.0~beta1: How to use an argument of Effect when their effect handler is not specified (Using Unhandled Exception)

I am using opam switch: 5.0.0~beta1
I was playing around with some simple functions (on utop):
type _ Effect.t += Foo : (unit -> unit) -> unit Effect.t
let a = try perform (Foo (fun () -> Printf.printf "Hello from Foo\n ")) with
| Unhandled (Foo f) -> f ();;
Output: Hello from Foo
val a: unit = ()
This works well.
But when we change the definition of Foo effect,
type _ Effect.t += Foo : ('a -> unit) -> unit Effect.t
let a = try perform (Foo (fun n -> Printf.printf "Hello from Foo\n ")) with
| Unhandled (Foo f) -> f 45;;
Error: This expression has type int but an expression was expected of type
$Foo_'a
Here I understand that it needs 'a as an input, but while calling the function, shouldnt it infer the type as int and replace 'a with int and execute the function accordingly? I want to call function f from Foo effect with different argument.
Here is the another example:
type _ Effect.t += Suspend : 'a -> unit Effect.t
let a = try perform (Suspend 32) with
| Unhandled (Suspend x) -> x;;
Error: This expression has type $Suspend_'a
but an expression was expected of type $Unhandled_'a
Here, I understand that return value of (try _ with) i.e. (unit) should be the type of $Unhandled_ 'a.
But I also want to know, what is $Unhandled_ 'a type? How is normal 'a is different from $Unhandled_ 'a? How to return $Unhandled_ 'a here? Why there is this special use of $Unhandled?
What will be its scope (In some examples where I was using following code,
type _ Effect.t += Foo : ('a -> unit) -> unit Effect.t
let p = try Lwt.return (some_function x) with
| Unhandled (Foo f) -> let (pr, res) = Lwt.task () in
let wkup v = (Lwt.wakeup res v; ()) in
f wkup;
pr
I also got error as :
This expression has type $Unhandled_'a Lwt.t
but an expression was expected of type 'a Lwt.t
The type constructor $Unhandled_'a would escape its scope
)?
Why there is
The type constructor $Unhandled_'a would escape its scope
error?
The effect part is a red-herring here, the root issue stems from the notion of existentially-quantified types in GADTs.
When you have a GADT which is defined as
type t = Foo : ('a -> unit) -> t
the type of Foo means that you can construct a t for any type 'a and any function of type 'a -> unit. For instance:
let l = [Foo ignore; Foo print_int]
However, once you have constructed such value, you can no longer knows which type was used to construct the value. If you have a value
let test (Foo f) = ...
you only know that there exists some type 'a such that f has type 'a -> unit. This why the type 'a is called an existentially type (aka a type such that we only know that it exists). The important things to remember is that you don't know which 'a. Consequently you cannot apply the function because applying to the wrong 'a would be a type error.
In other words, the function boxed in Foo f can never be called on any value.
This is slightly more subtle variant than the any type
type any = Any: 'a -> any
where the constructor Any takes a value of any type and put it in a black box from which it can never be extracted.
In a way existentially-quantified type variables in a GADT lives in their own world and they cannot escape it. But they can be still be useful if this inner world is large enough. For instance, I can bundle a value with a function that prints that value and then forget the type of this value with:
type showable = Showable: {x:'a; print:'a -> unit} -> showable
Here, I can call the function print on the value x because I know that whatever is 'a it is the same 'a for both x and print:
let show (Showable {x;print}) = print x
Thus I can store few showable values in a list
let l = [ Showable(0, print_int), Showable("zero", print_string)]
and print them later
let () = List.iter show l

Implementing functions in Haskell

I'm trying to implement an eval function using my own type aliases and data constructor. This function is supposed to return an updated dictionary Dict and program counter Counter according to the Func inputted. Basically, I want it to increment the counter if an input is correct.
These are my type aliases:
type Counter = Int
type Name = String
type Dict = Map Name Const
This is a type I created to be used in a later the class I mention below:
data Func = GET_INT Int
| GET_DICT Name
| JUMP Counter
deriving Show
And this is the class with the function and where I'm making Func an instance of it:
class Evaluate a where
eval :: Func -> (Dict, Counter) -> Maybe (Dict, Counter)
instance Evaluate Func where
eval (GET_INT a)(d, c) = Just(d, c+1)
eval (GET_DICT a)(d, c) = Just(d, c+1)
eval (JUMP a)(d, c) = Just(d, c+1)
eval = Nothing
However, I am getting some errors. First of all, I am getting the following: Expected a type, but 'Counter' has kind 'Const'
Secondly, I am not sure I entered the correct parameters for the Evaluate class, as a is not being used anywhere. Also, I don't think the inputs for the function will work as they are above.
Can anyone help figure out how to get the function to work?
These are my types:
type Counter = Int
type Name = String
type Dict = Map Name Int
Those are type aliases, but ok.
This is my dataclass:
data Func = GET_INT Int
| GET_DICT Name
deriving Show
The term "dataclass" doesn't mean anything. Func is a type. There are two data constructors. Ok.
And this is the class with the function I'm trying to create:
class Evaluate a where
eval :: a -> (Dict, Counter) -> Maybe (Dict, Counter)
Well that doesn't make much sense. What is eval and why should it be parameterized by a? I think you'd be better served by just defining eval :: Func -> (Dict, Counter) -> Maybe (Dict, Counter) first and thinking hard about why you'd want to make it more polymorphic.
eval (GET_INT a)([(d1, d2)],c) = ([(d1,d2)], c)
eval (GET_DICT a)([(d1, d2)],c) = ([(d1,d2)], c)
This is the error I'm getting: Equations for `eval' have different numbers of arguments.
No. With the code you presented this is not the error. You should always provide the actual code used to produce the error causing your confusion.
Actual error number one:
so.hs:15:20: error:
• Couldn't match type ‘[(a0, b0)]’ with ‘Map Name Int’
Expected type: Dict
Actual type: [(a0, b0)]
• In the pattern: [(d1, d2)]
In the pattern: ([(d1, d2)], c)
In an equation for ‘eval’:
eval (GET_INT a) ([(d1, d2)], c) = ([(d1, d2)], c)
|
15 | eval (GET_INT a)([(d1, d2)],c) = ([(d1,d2)], c)
This is because, with small exception, the syntax [ ... ] is a list and not a Map. You can not pattern match on maps and should just match a variable such as env.
so.hs:15:36: error:
• Couldn't match expected type ‘Maybe (Dict, Counter)’
with actual type ‘([(a0, b0)], Counter)’
• In the expression: ([(d1, d2)], c)
In an equation for ‘eval’:
eval (GET_INT a) ([(d1, d2)], c) = ([(d1, d2)], c)
In the instance declaration for ‘Evaluate Func’
• Relevant bindings include
d2 :: b0 (bound at so.hs:15:26)
d1 :: a0 (bound at so.hs:15:22)
|
15 | eval (GET_INT a)([(d1, d2)],c) = ([(d1,d2)], c)
A tuple of (a,b) is not the same as Maybe (a,b). Sadly you evidently already knew this but pasted distracting code - clean up the code prior to asking the question.
If we fix these two issues then we get code that loads fine but is entirely worthless:
import Data.Map
type Counter = Int
type Name = String
type Dict = Map Name Int
data Func = GET_INT Int
| GET_DICT Name
deriving Show
class Evaluate a where
eval :: a -> (Dict, Counter) -> Maybe (Dict, Counter)
instance Evaluate Func where
eval (GET_INT a) (env,c) = Just (env, c)
eval (GET_DICT a) (env,c) = Just (env, c)

Coq: Defining a function by pattern matching on the arity of its argument

I want to define a function, the behavior of which depends on whether it's argument is (at least) an n-place function. A rudimentary (failed) attempt is
Definition rT {y:Type}(x:y) := ltac: (match y with
| _ -> _ -> _ => exact True
| _ => exact False end).
Check prod: Type -> Type -> Type.
Compute rT prod. (*= False: Prop*)
Print rT. (*rT = fun (y : Type) (_ : y) => False: forall y : Type, y -> Prop*)
As you see, rT maps everything to False. Why? The result remains the same if I replace y in the match clause w/ type of x
The function you want cannot exist within Gallina at the type you expect.
Your function is accepted, but if you print it, you can see its body is:
rT = fun (y : Type) (_ : y) => False
Gallina has no way of match-ing on a Type. There are ways to deal with n-ary functions, in such a way that you can inspect their arity, but it involves dependent types to statically capture the arity. For instance, for uniform n-ary functions:
https://coq.inria.fr/library/Coq.Numbers.NaryFunctions.html

Why can't I label the argument of a function that just raises an exception?

I am trying to write a function that just raises an exception. It works, but I cannot use it within another function when the argument is labeled.
Here is a simple example:
let raise_error ~m = failwith m
let test = function
| true -> raise_error "ok"
| false -> raise_error "ko"
There is a warning, and the function does not have the type I expected:
Warning 20: this argument will not be used by the function.
Warning 20: this argument will not be used by the function.
val test : bool -> m:string -> 'a = <fun>
This other function fails to compile:
let test2 = function
| true -> "ok"
| false -> raise_error "ko"
with the message:
Warning 20: this argument will not be used by the function.
Error: This expression has type m:string -> 'a
but an expression was expected of type string
I don't understand what's wrong, because it works if the argument is not labeled.
Is there a way to get around this?
You could label the arguments at the call sites:
let raise_error ~m = failwith m
let test = function
| true -> raise_error ~m:"ok"
| false -> raise_error ~m:"ko"
let test2 = function
| true -> "ok"
| false -> raise_error ~m:"ko"
A better solution is to rewrite raise_error to not use labelled arguments.
The issue is that raise_error as written has a type of m:string -> 'a, so you can pass it any number of non-labelled arguments and the resulting expression will still be a function of type m:string -> 'a. This is error prone and surprising, so you should avoid using labelled arguments with diverging functions.

FSharpTypeFunc.Specialize causing TypeLoadException

I'm getting the following run-time exception:
System.TypeLoadException was unhandled
Message=Method 'Specialize' on type [...] tried to implicitly override a method with weaker type parameter constraints.
This inner function appears to be the problem:
let getKey (r: IDictionary<_,_>) =
match r.TryGetValue(keyCol.Name) with
| true, k when not (isNull k) -> Some k
| _ -> None
The signature is IDictionary<string,'a> -> 'a option (requires 'a : null). The constraint is propagated from isNull.
Looking in ILSpy, getKey is compiled to a sub-type of FSharpTypeFunc that overrides Specialize<T>().
Is this a bug? I can work around it by boxing k in the call to isNull, which removes the constraint.
EDIT
Here's a full repro:
open System.Collections.Generic
let isNull = function null -> true | _ -> false
type KeyCol = { Name : string }
let test() =
seq {
let keyCol = { Name = "" }
let getKey (r: IDictionary<_,_>) =
match r.TryGetValue(keyCol.Name) with
| true, k when not (isNull k) -> Some k
| _ -> None
getKey (dict ["", box 1])
}
test() |> Seq.length |> printfn "%d"
This is a console app in Visual Studio 2008, targeting .NET 4.0. Strangely, the code works in FSI.
Here's PEVerify output for the assembly:
[token 0x02000004] Type load failed.
[IL]: Error: [D:\TEST\bin\Debug\TEST.exe : Test+test#10[a]::GenerateNext] [mdToken=0x6000012][offset 0x00000031] Unable to resolve token.
2 Error(s) Verifying D:\TEST\bin\Debug\TEST.exe
Sent it to fsbugs and received a reply that it's been fixed.