OCaml 5.0.0~beta1: How to use an argument of Effect when their effect handler is not specified (Using Unhandled Exception) - 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

Related

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)

F# generics / function overloading syntax

I'm confused on how to label a function as generic without an explicit type declaration like ('a -> 'a)
let add a b = a + b
This gives us
val add : a:int -> b:int -> int
However we can then immediately call
add "Hello " "World!"
and now the value of add is
val add : a:string -> b:string -> string
val it : string = "Hello World!"
If we then call
add 2 3 // then we get
error: This expression was expected to have type string but here has type int
How do I ensure that a function works on all types that say have the function (+) defined
This is F#'s embarrassing skeleton in the closet.
Try this:
> let mapPair f (x,y) = (f x, f y)
val mapPair : f:('a -> 'b) -> x:'a * y:'a -> 'b * 'b
Fully generic! Clearly, function application and tuples work.
Now try this:
> let makeList a b = [a;b]
val makeList : a:'a -> b:'a -> 'a list
Hmmm, also generic. How about this:
> let makeList a b = [a + b]
val makeList : a:int -> b:int -> int list
Aha, as soon as I have a (+) in there, it becomes int for some reason.
Let's keep playing:
> let inline makeList a b = [a + b]
val inline makeList :
a: ^a -> b: ^b -> ^c list
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
Hmmm, interesting. Turns out, if I make the function inline, then F# does consider it generic, but it also gives it this weird when clause, and my generic parameters have this strange ^ symbol instead of the usual tick.
This strange syntax is called "statically resolved type parameters" (see here for a somewhat coherent explanation), and the basic idea is that the function (+) requires its arguments to have a static member (+) defined. Let's verify:
> let x = 0 :> obj
let y = 0 :> obj
let z = x + y
Script1.fsx(14,13): error FS0001: The type 'obj' does not support the operator '+'
> type My() =
static member (+)( a:My, b:My ) = My()
let x = My()
let y = My()
let z = x + y
val x : My
val y : My
val z : My
Now, the problem with this is that CLR does not support this kind of generic parameters (i.e. "any type, as long as it has such and such members"), so F# has to fake it and resolve these calls at compile time. But because of this, any methods that use this feature cannot be compiled to true generic IL methods, and thus have to be monomorphised (which is enabled by inline).
But then, it would be very inconvenient to require that every function that uses arithmetic operators be declared inline, wouldn't it? So F# goes yet another extra step and tries to fix these statically resolved generic parameters based on how they are instantiated later in the code. That's why your function turns into string->string->string as soon as you use it with a string once.
But if you mark your function inline, F# wouldn't have to fix parameters, because it wouldn't have to compile the function down to IL, and so your parameters remain intact:
> let inline add a b = a + b
val inline add :
a: ^a -> b: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
If I understand you correctly, use inline:
let inline add a b = a + b
add 2 3 |> printfn "%A"
add "Hello " "World!" |> printfn "%A"
Print:
5
"Hello World!"
Link: http://ideone.com/awsYNI
Make it inline
let inline add a b = a + b
(*
val inline add :
a: ^a -> b: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
*)
add "Hello " "World!"
// val it : string = "Hello World!"
add 2 3
// val it : int = 5

Using a function twice using map

I want a function used twice on a String. I'm gonna explain what i want so I hope at the end of the question you get what i mean.
So i have this function.
foo :: String -> [String]
foo = ...
Now i want that this function is used twice on a String. So when used first it should run foo with the String that is given to the function and on the second run it should used on every String from the [String] that is produced by the first run. So i guessed that map is the best function to do that.
So i got this function now
f :: String -> [String]
f w = map foo (foo w)
But the compliler gives me this error:
MyHaskell.hs:86:19:
Couldn't match type `[Char]' with `Char'
Expected type: String -> String
Actual type: String -> [String]
In the first argument of `map', namely `edits1'
In the expression: map edits1 (edits1 word)
I guess the problem is that my function foo (String -> [String]) does not work out with map ((a->b) -> [a] -> [b]).
How do i fix that?
You were very close.
f :: String -> [[String]]
f w = map foo (foo w)
You just got the type signature wrong - if you are applying foo to each element, each element becomes a [String] so you need a nested list.
#alternative brought me to this answer.
I have to concat the result so i'll get [String] as a result.
f :: String -> [String]
f w = concat (map foo (foo w))
This is shorter, but same thing:
double_map2 f g xs = map (f . g) xs

Int and Num type of haskell

I have below code to take the args to set some offset time.
setOffsetTime :: (Ord a, Num b)=>[a] -> b
setOffsetTime [] = 200
setOffsetTime (x:xs) = read x::Int
But compiler says "Could not deduce (b ~ Int) from the context (Ord a, Num b) bound by the type signature for setOffsetTime :: (Ord a, Num b) => [a] -> b
Also I found I could not use 200.0 if I want float as the default value. The compilers says "Could not deduce (Fractional b) arising from the literal `200.0'"
Could any one show me some code as a function (not in the prelude) that takes an arg to store some variable so I can use in other function? I can do this in the main = do, but hope
to use an elegant function to achieve this.
Is there any global constant stuff in Hasekll? I googled it, but seems not.
I wanna use Haskell to replace some of my python script although it is not easy.
I think this type signature doesn't quite mean what you think it does:
setOffsetTime :: (Ord a, Num b)=>[a] -> b
What that says is "if you give me a value of type [a], for any type a you choose that is a member of the Ord type class, I will give you a value of type b, for any type b that you choose that is a member of the Num type class". The caller gets to pick the particular types a and b that are used each time setOffsetTime is called.
So trying to return a value of type Int (or Float, or any particular type) doesn't make sense. Int is indeed a member of the type class Num, but it's not any member of the type class Num. According to that type signature, I should be able to make a brand new instance of Num that you've never seen before, import setOffsetTime from your module, and call it to get a value of my new type.
To come up with an acceptable return value, you can only use functions that likewise return an arbitrary Num. You can't use any functions of particular concrete types.
Existential types are essentially a mechanism for allowing the callee to choose the value for a type variable (and then the caller has to be written to work regardless of what that type is), but that's not really something you want to be getting into while you're still learning.
If you are convinced that the implementation of your function is correct, i.e., that it should interpret the first element in its input list as the number to return and return 200 if there is no such argument, then you only need to make sure that the type signature matches that implementation (which it does not do, right now).
To do so, you could, for example, remove the type signature and ask ghci to infer the type:
$ ghci
GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :{
Prelude| let setOffsetTime [] = 200
Prelude| setOffsetTime (x : xs) = read x :: Int
Prelude| :}
Prelude> :t setOffsetTime
setOffsetTime :: [String] -> Int
Prelude> :q
Leaving GHCi.
$
And indeed,
setOffsetTime :: [String] -> Int
setOffsetTime [] = 200
setOffsetTime (x : xs) = read x :: Int
compiles fine.
If you want a slightly more general type, you can drop the ascription :: Int from the second case. The above method then tells you that you can write
setOffsetTime :: (Num a, Read a) => [String] -> a
setOffsetTime [] = 200
setOffsetTime (x : xs) = read x
From the comment that you added to your question, I understand that you want your function to return a floating-point number. In that case, you can write
setOffsetTime :: [String] -> Float
setOffsetTime [] = 200.0
setOffsetTime (x : xs) = read x
or, more general:
setOffsetTime :: (Fractional a, Read a) => [String] -> a
setOffsetTime [] = 200.0
setOffsetTime (x : xs) = read x

Ocaml exception handling for opening input channel

As a beginner in Ocaml, I have this current working code:
...
let ch_in = open_in input_file in
try
proc_lines ch_in
with End_of_file -> close_in ch_in;;
Now I would like to add error handling for non-existing input files, I wrote this:
let ch_in = try Some (open_in input_file) with _ -> None in
match ch_in with
| Some x -> try proc_lines x with End_of_file -> close_in x
| None -> () ;;
and get an error message: This pattern matches values of type 'a option
but is here used to match values of type exn for the last line. If I substitute None for _, I get an error about incomplete matching.
I read that exn is the exception type. I'm sure I don't understand what is really going on here, so please point me to the right direction. Thanks!
When embedding pattern matches inside other pattern matches you need to encase the embedded match with either ( ... ) or begin ... end (syntactic sugar for parentheses):
let ch_in = try Some (open_in input_file) with _ -> None in
match ch_in with
| Some x -> (try proc_lines x with End_of_file -> close_in x)
| None -> () ;;