Given the following code :
exception E of int;
fun g(y) = raise E(y);
fun f(x) =
let
exception E of real;
fun z(y)= raise E(y);
in
x(3.0);
z(3)
end;
f(g);
When executing the code in SML I get :
stdIn:216.8-216.12 Error: operator and operand don't agree [literal]
operator domain: real
operand: int
in expression:
z 3
That's fine - I understand that the line z(3); causes an error , since z throws int instead of real .
But my problem is with the line x(3.0); , why doesn't it cause an error ?
From my understanding , x is g(y) , then when we execute x(3.0) we actually execute g(3.0) , but g throws only exceptions of type int , but we passed to g the value 3.0 ,hence g would throw a real value , so it's supposed to be a violation , doesn't it ?
I'd appreciate if someone can explain why no error is happening when executing x(3.0) .
Thanks
EDIT:
When I remove z(3); , meaning :
- fun f(x) =
= let
= exception E of real;
= fun z(y)= raise E(y);
= in
= x(3.0)
=
= end;
val f = fn : (real -> 'a) -> 'a
- f(g);
The output is :
stdIn:11.1-11.5 Error: operator and operand don't agree [tycon mismatch]
operator domain: real -> 'Z
operand: int -> 'Y
in expression:
f g
-
So , as U can see , in both cases we'll get error .
Hence , I'm back at square one : why when both x(3.0) and z(3) appear (see code 1 , the first code posted at the beginning of the post) one after the other , why does SML only refers to the error that the second line (z(3);) caused , and not to the error that
the first line caused (x(3.0);) .
10x again
To complement Jesper's excellent answer: In other words, there is nothing wrong with the call to x inside f. If you remove the erroneous call to z, and then type f into an SML prompt, then you should see that the type system has inferred the type
(real -> 'a) -> 'a
for it. That type is perfectly fine, it is merely the call to f later on in your program that is ill-typed. because g does not match the parameter type real -> 'a as required.
Your problem lies in the fact that x is a function that is passed along to f, thus when typing the function f, it will always give the correct type to the argument x, as it is not bound by anything. The fact that you are have a function application f(g) right after plays no role when inferring the types of the function f.
If we move the local function z outside the definition of f, we end up with something a lot simpler, which will type
exception R of real;
fun z(y)= raise R (y);
exception I of int;
fun g(y) = raise I (y);
fun f(i, r) = (i(3.0); r(3))
However when we then call f(g,z) we end up with the following error, as the two functions aren't of the correct type
- f(g, z);
stdIn:78.1-78.8 Error: operator and operand don't agree [tycon mismatch]
operator domain: (real -> 'Z) * (int -> 'Y)
operand: (int -> 'X) * (real -> 'W)
in expression:
f (g,z)
The initial misunderstanding stemmed from not understanding when the type error was detected. Standard ML is a strongly STATICALLY typed language. This means that the type checking is all done at compile time, when the function is first read by the interpreter, not at run-time. This means that the type error is generated before the code is ever executed, which Jesper correctly pointed out. The two type errors are exactly where Jesper indicated, in the f(g) expression and the z(3) expression. There is nothing wrong with the expression x(3.0) when the expression is compiled. There would only be a problem there if static type checking did not prevent the program from running at all. A dynamically typed language like Python would allow this program to run and raise an exception where Ron suggests when the x(3.0) expression was evaluated.
Related
I am trying to define a parser in Haskell. I am a total beginner and somehow didn't manage to find any solution to my problem at all.
For the first steps I tried to follow the instructions on the slides of a powerpoint presentation. But I constantly get the error "Not in scope: type variable ‘a’":
type Parser b = a -> [(b,a)]
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x:xs)]
error: Not in scope: type variable ‘a’
|
11 | type Parser b = a -> [(b,a)]
| ^
I don't understand the error but moreover I don't understand the first line of the code as well:
type Parser b = a -> [(b,a)]
What is this supposed to do? On the slide it just tells me that in Haskell, Parsers can be defined as functions. But that doesn't look like a function definition to me. What is "type" doing here? If it s used to specify the type, why not use "::" like in second line above? And "Parser" seems to be a data type (because we can use it in the type definition of "item"). But that doesn't make sense either.
The line derives from:
type Parser = String -> (String, Tree)
The line I used in my code snippet above is supposed to be a generalization of that.
Your help would be much appreciated. And please bear in mind that I hardly know anything about Haskell, when you write an answer :D
There is a significant difference between the type alias type T = SomeType and the type annotation t :: SomeType.
type T = Int simply states that T is just another name for the type Int. From now on, every time we use T, it will be replaced with Int by the compiler.
By contrast, t :: Int indicates that t is some value of type Int. The exact value is to be specified by an equation like t = 42.
These two concepts are very different. On one hand we have equations like T = Int and t = 42, and we can replace either side with the other side, replacing type with types and values with values. On the other hand, the annotation t :: Int states that a value has a given type, not that the value and the type are the same thing (which is nonsensical: 42 and Int have a completely different nature, a value and a type).
type Parser = String -> (String, Tree)
This correctly defines a type alias. We can make it parametric by adding a parameter:
type Parser a = String -> (String, a)
In doing so, we can not use variables in the right hand side that are not parameters, for the same reason we can not allow code like
f x = x + y -- error: y is not in scope
Hence you need to use the above Parser type, or some variation like
type Parser a = String -> [(String, a)]
By contrast, writing
type Parser a = b -> [(b, a)] -- error
would use an undeclared type b, and is an error. At best, we could have
type Parser a b = b -> [(b, a)]
which compiles. I wonder, though, is you really need to make the String type even more general than it is.
So, going back to the previous case, a possible way to make your code run is:
type Parser a = String -> [(a, String)]
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x, xs)]
Note how [(x, xs)] is indeed of type [(Char, String)], as needed.
If you really want to generalize String as well, you need to write:
type Parser a b = b -> [(b, a)]
item :: Parser Char String
item = \inp -> case inp of
[] -> []
(x:xs) -> [(xs, x)]
I am working on the Haskell project,
For the error checking, I need to take care of any function call having too many or too few arguments, but I currently have no idea for it.Hoping to get same hints to start.
Unless one uses some form of advanced ad hoc polymorphism like the printf :: PrintfType r => String -> r does, the compiler will notice.
Indeed, if you have a function like:
add :: Int -> Int -> Int
add = (+)
if you call it with three parameters, like add 2 4 5, then this will raise an error. This will happen, since add 2 4 5, or more canonical ((add 2) 4) 5, will try to eventually make a call to an item that is an Int. Indeed add 2 has type add 2 :: Int -> Int, and thus (add 2) 4 has type (add 2) 4 :: Int, so since that is not function, the compiler will raise an error:
Prelude> add 2 4 5
<interactive>:5:1: error:
• Couldn't match expected type ‘Integer -> t’
with actual type ‘Int’
• The function ‘add’ is applied to three arguments,
but its type ‘Int -> Int -> Int’ has only two
In the expression: add 2 4 5
In an equation for ‘it’: it = add 2 4 5
• Relevant bindings include it :: t (bound at <interactive>:5:1)
It thus says it expected a type (Integer -> t, although the Integer here is due to type defaulting), but got an Int instead. So that is not possible.
Calling a function with "too few" parameters is not really possible, since if you call it with too few, you simply generate a function that expects to take the next parameter. This is the idea behind currying [Haskell-wiki]. Indeed, if the type of add 2 is:
Prelude> :t add 2
add 2 :: Int -> Int
It is a function that expects the following parameter. It is possible that this will clash with another function that expects an Int, but then you will get a similar exception except that the expected will be a non-function (Int) for example, and the actual type is a function, so something like:
• Couldn't match expected type ‘Int’
with actual type ‘Integer -> t’
Haskell's type system will thus error in case you call a function with too much arguments, or when you use the result of a function with too few arguments.
Note that strictly speaking in Haskell every function only takes one parameter. If you do not provide one, then the outcome is still a function, if you provide one, you make a function call, but that function can produce another function thus expects the next parameter.
The reason that printf can take one, two, or more parameters, is because of the instances of the PrintfType type class. This can be an IO a that will thus then print the result of the formatted string, or a function (PrintfArg a, PrintfType r) => a -> r that thus will take a parameter of the PrintfArg type, and return another PrintfType type. It can thus each time specialize in an extra function if another function is necessary. But this thus emulates a variadic function, where you can pass an arbitrary number of parameters.
[...] a pair of functions tofun : int -> ('a -> 'a) and fromfun : ('a -> 'a) ->
int such that (fromfun o tofun) n evaluates to n for every n : int.
Anyone able to explain to me what this is actually asking for? I'm looking for more of an explanation of that than an actual solution to this.
What this is asking for is:
1) A higher-order function tofun which when given an integer returns a polymorphic function, one which has type 'a->'a, meaning that it can be applied to values of any type, returning a value of the same type. An example of such a function is:
- fun id x = x;
val id = fn : 'a -> 'a
for example, id "cat" = "cat" and id () = (). The later value is of type unit, which is a type with only 1 value. Note that there is only 1 total function from unit to unit (namely, id or something equivalent). This underscores the difficulty with coming up with defining tofun: it returns a function of type 'a -> 'a, and other than the identity function it is hard to think of other functions. On the other hand -- such functions can fail to terminate or can raise an error and still have type 'a -> 'a.
2) fromfun is supposed to take a function of type 'a ->'a and return an integer. So e.g. fromfun id might evaluate to 0 (or if you want to get tricky it might never terminate or it might raise an error)
3) These are supposed to be inverses of each other so that, e.g. fromfun (tofun 5) needs to evaluate to 5.
Intuitively, this should be impossible in a sufficiently pure functional language. If it is possible in SML, my guess is that it would be by using some of the impure features of SML (which allow for side effects) to violate referential transparency. Or, the trick might involve raising and handling errors (which is also an impure feature of SML). If you find an answer which works in SML it would be interesting to see if it could be translated to the annoyingly pure functional language Haskell. My guess is that it wouldn't translate.
You can devise the following property:
fun prop_inverse f g n = (f o g) n = n
And with definitions for tofun and fromfun,
fun tofun n = ...
fun fromfun f = ...
You can test that they uphold the property:
val prop_test_1 =
List.all
(fn i => prop_inverse fromfun tofun i handle _ => false)
[0, ~1, 1, valOf Int.maxInt, valOf Int.minInt]
And as John suggests, those functions must be impure. I'd also go with exceptions.
fun first_answer(my_f:('a -> 'b option)) : 'a list -> 'b =
let
fun help(_a:'a list) : 'a =
(((List.map valOf)o(List.filter isSome)o(List.map my_f)) _a)
in
help
end;
Error: syntax error: replacing WILD with SEMICOLON
Something with that _a is messing it up..... The error is linked to the last usage of _a
I am not getting very far, and I've rearranged the logic many ways already. As you can see the first_answer returns takes a function and returns a function. This is what I am doing here and I am following the types as far as I know. There is probably something simple that I am not seeing.
It's simple indeed: an identifier cannot start with an underscore. So _a is parsed as if you had written _ a, in accordance with the usual maximal munch rule for lexical syntax.
Edit: Extra tip: Your function does not have the type 'a list -> 'b, because help returns a list of 'bs, not a single value of type 'b. Moreover, as written, it can be implemented more easily as
fun first_answer f xs = List.mapPartial f xs
or, in fact,
val first_answer = List.mapPartial
I am currently trying to define a function of type ('a -> 'a) -> 'a -> 'a which takes a function of type 'a -> 'a and an argument of type 'a and calls the function twice on the argument. I'm relatively new to OCaml but I do know how to define a function, but I had no luck with trial and error or Google trying to get a function to take a function as an argument and then apply that function twice.
Any tips or pointers would be greatly appreciated, thanks in advance.
edit: Thanks to Jeffrey below, my problem is now solved.
let f4 g a = g (g a );;
val f4 : ('a -> 'a) -> 'a -> 'a =
OCaml infers types, so if you use an argument as a function, it infers that it's a function. Here's an example:
# let f g = g 8 + g 10;;
val f : (int -> int) -> int = <fun>
# (~-);;
- : int -> int = <fun>
# f (~-);;
- : int = -18
To understand the example, note that (~-) is the ordinary integer negation operator.
Update: A hint for your more complicated problem. You need to test the value of n. Maybe an if statement would work? Second hint: if you use recursion, you don't need to use a loop. If you want to use a loop, don't use recursion. (Personally I'd suggest using recursion, it's like playing scales while learning piano.)