I'm an OCaml noob. I'm trying to figure out how to handle a comparison operator that's passed into a function.
My function just tries to pass in a comparison operator (=, <, >, etc.) and an int.
let myFunction comparison x =
if (x (comparison) 10) then
10
else
x;;
I was hoping that this code would evaluate to (if a "=" were passed in):
if (x = 10) then
10
else
x;;
However, this is not working. In particular, it thinks that x is a bool, as evidenced by this error message:
This expression has type 'a -> int -> bool
but an expression was expected of type int
How can I do what I'm trying to do?
On a side question, how could I have figured this out on my own so I don't have to rely on outside help from a forum? What good resources are available?
Comparison operators like < and = are secretly two-parameter (binary) functions. To pass them as a parameter, you use the (<) notation. To use that parameter inside your function, you just treat it as function name:
let myFunction comp x =
if comp x 10 then
10
else
x;;
printf "%d" (myFunction (<) 5);; (* prints 10 *)
OCaml allows you to treat infix operators as identifiers by enclosing them in parentheses. This works not only for existing operators but for new ones that you want to define. They can appear as function names or even as parameters. They have to consist of symbol characters, and are given the precedence associated with their first character. So if you really wanted to, you could use infix notation for the comparison parameter of myFunction:
Objective Caml version 3.12.0
# let myFunction (#) x =
x # 10;;
val myFunction : ('a -> int -> 'b) -> 'a -> 'b = <fun>
# myFunction (<) 5;;
- : bool = true
# myFunction (<) 11;;
- : bool = false
# myFunction (=) 10;;
- : bool = true
# myFunction (+) 14;;
- : int = 24
#
(It's not clear this makes myFunction any easier to read. I think definition of new infix operators should be done sparingly.)
To answer your side question, lots of OCaml resources are listed on this other StackOverflow page:
https://stackoverflow.com/questions/2073436/ocaml-resources
Several possibilities:
Use a new definition to redefine your comparison operator:
let myFunction comparison x =
let (#) x y = comparison x y in
if (x # 10) then
10
else
x;;
You could also pass the # directly without the extra definition.
As another solution you can use some helper functions to define what you need:
let (/*) x f = f x
let (*/) f x = f x
let myFunction comparison x =
if x /* comparison */ 10 then
10
else
x
Related
I made this function in Python:
def calc(a): return lambda op: {
'+': lambda b: calc(a+b),
'-': lambda b: calc(a-b),
'=': a}[op]
So you can make a calculation like this:
calc(1)("+")(1)("+")(10)("-")(7)("=")
And the result will be 5.
I wanbt to make the same function in Haskell to learn about lambdas, but I am getting parse errors.
My code looks like this:
calc :: Int -> (String -> Int)
calc a = \ op
| op == "+" = \ b calc a+b
| op == "-" = \ b calc a+b
| op == "=" = a
main = calc 1 "+" 1 "+" 10 "-" 7 "="
There are numerous syntactical problems with the code you have posted. I won't address them here, though: you will discover them yourself after going through a basic Haskell tutorial. Instead I'll focus on a more fundamental problem with the project, which is that the types don't really work out. Then I'll show a different approach that gets you the same outcome, to show you it is possible in Haskell once you've learned more.
While it's fine in Python to sometimes return a function-of-int and sometimes an int, this isn't allowed in Haskell. GHC has to know at compile time what type will be returned; you can't make that decision at runtime based on whether a string is "=" or not. So you need a different type for the "keep calcing" argument than the "give me the answer" argument.
This is possible in Haskell, and in fact is a technique with a lot of applications, but it's maybe not the best place for a beginner to start. You are inventing continuations. You want calc 1 plus 1 plus 10 minus 7 equals to produce 5, for some definitions of the names used therein. Achieving this requires some advanced features of the Haskell language and some funny types1, which is why I say it is not for beginners. But, below is an implementation that meets this goal. I won't explain it in detail, because there is too much for you to learn first. Hopefully after some study of Haskell fundamentals, you can return to this interesting problem and understand my solution.
calc :: a -> (a -> r) -> r
calc x k = k x
equals :: a -> a
equals = id
lift2 :: (a -> a -> a) -> a -> a -> (a -> r) -> r
lift2 f x y = calc (f x y)
plus :: Num a => a -> a -> (a -> r) -> r
plus = lift2 (+)
minus :: Num a => a -> a -> (a -> r) -> r
minus = lift2 (-)
ghci> calc 1 plus 1 plus 10 minus 7 equals
5
1 Of course calc 1 plus 1 plus 10 minus 7 equals looks a lot like 1 + 1 + 10 - 7, which is trivially easy. The important difference here is that these are infix operators, so this is parsed as (((1 + 1) + 10) - 7), while the version you're trying to implement in Python, and my Haskell solution, are parsed like ((((((((calc 1) plus) 1) plus) 10) minus) 7) equals) - no sneaky infix operators, and calc is in control of all combinations.
chi's answer says you could do this with "convoluted type class machinery", like printf does. Here's how you'd do that:
{-# LANGUAGE ExtendedDefaultRules #-}
class CalcType r where
calc :: Integer -> String -> r
instance CalcType r => CalcType (Integer -> String -> r) where
calc a op
| op == "+" = \ b -> calc (a+b)
| op == "-" = \ b -> calc (a-b)
instance CalcType Integer where
calc a op
| op == "=" = a
result :: Integer
result = calc 1 "+" 1 "+" 10 "-" 7 "="
main :: IO ()
main = print result
If you wanted to make it safer, you could get rid of the partiality with Maybe or Either, like this:
{-# LANGUAGE ExtendedDefaultRules #-}
class CalcType r where
calcImpl :: Either String Integer -> String -> r
instance CalcType r => CalcType (Integer -> String -> r) where
calcImpl a op
| op == "+" = \ b -> calcImpl (fmap (+ b) a)
| op == "-" = \ b -> calcImpl (fmap (subtract b) a)
| otherwise = \ b -> calcImpl (Left ("Invalid intermediate operator " ++ op))
instance CalcType (Either String Integer) where
calcImpl a op
| op == "=" = a
| otherwise = Left ("Invalid final operator " ++ op)
calc :: CalcType r => Integer -> String -> r
calc = calcImpl . Right
result :: Either String Integer
result = calc 1 "+" 1 "+" 10 "-" 7 "="
main :: IO ()
main = print result
This is rather fragile and very much not recommended for production use, but there it is anyway just as something to (eventually?) learn from.
Here is a simple solution that I'd say corresponds more closely to your Python code than the advanced solutions in the other answers. It's not an idiomatic solution because, just like your Python one, it will use runtime failure instead of types in the compiler.
So, the essence in you Python is this: you return either a function or an int. In Haskell it's not possible to return different types depending on runtime values, however it is possible to return a type that can contain different data, including functions.
data CalcResult = ContinCalc (Int -> String -> CalcResult)
| FinalResult Int
calc :: Int -> String -> CalcResult
calc a "+" = ContinCalc $ \b -> calc (a+b)
calc a "-" = ContinCalc $ \b -> calc (a-b)
calc a "=" = FinalResult a
For reasons that will become clear at the end, I would actually propose the following variant, which is, unlike typical Haskell, not curried:
calc :: (Int, String) -> CalcResult
calc (a,"+") = ContinCalc $ \b op -> calc (a+b,op)
calc (a,"-") = ContinCalc $ \b op -> calc (a-b,op)
calc (a,"=") = FinalResult a
Now, you can't just pile on function applications on this, because the result is never just a function – it can only be a wrapped function. Because applying more arguments than there are functions to handle them seems to be a failure case, the result should be in the Maybe monad.
contin :: CalcResult -> (Int, String) -> Maybe CalcResult
contin (ContinCalc f) (i,op) = Just $ f i op
contin (FinalResult _) _ = Nothing
For printing a final result, let's define
printCalcRes :: Maybe CalcResult -> IO ()
printCalcRes (Just (FinalResult r)) = print r
printCalcRes (Just _) = fail "Calculation incomplete"
printCalcRes Nothing = fail "Applied too many arguments"
And now we can do
ghci> printCalcRes $ contin (calc (1,"+")) (2,"=")
3
Ok, but that would become very awkward for longer computations. Note that we have after two operations a Maybe CalcResult so we can't just use contin again. Also, the parentheses that would need to be matched outwards are a pain.
Fortunately, Haskell is not Lisp and supports infix operators. And because we're anyways getting Maybe in the result, might as well include the failure case in the data type.
Then, the full solution is this:
data CalcResult = ContinCalc ((Int,String) -> CalcResult)
| FinalResult Int
| TooManyArguments
calc :: (Int, String) -> CalcResult
calc (a,"+") = ContinCalc $ \(b,op) -> calc (a+b,op)
calc (a,"-") = ContinCalc $ \(b,op) -> calc (a-b,op)
calc (a,"=") = FinalResult a
infixl 9 #
(#) :: CalcResult -> (Int, String) -> CalcResult
ContinCalc f # args = f args
_ # _ = TooManyArguments
printCalcRes :: CalcResult -> IO ()
printCalcRes (FinalResult r) = print r
printCalcRes (ContinCalc _) = fail "Calculation incomplete"
printCalcRes TooManyArguments = fail "Applied too many arguments"
Which allows to you write
ghci> printCalcRes $ calc (1,"+") # (2,"+") # (3,"-") # (4,"=")
2
A Haskell function of type A -> B has to return a value of the fixed type B every time it's called (or fail to terminate, or throw an exception, but let's neglect that).
A Python function is not similarly constrained. The returned value can be anything, with no type constraints. As a simple example, consider:
def foo(b):
if b:
return 42 # int
else:
return "hello" # str
In the Python code you posted, you exploit this feature to make calc(a)(op) to be either a function (a lambda) or an integer.
In Haskell we can't do that. This is to ensure that the code can be type checked at compile-time. If we write
bar :: String -> Int
bar s = foo (reverse (reverse s) == s)
the compiler can't be expected to verify that the argument always evaluates to True -- that would be undecidable, in general. The compiler merely requires that the type of foo is something like Bool -> Int. However, we can't assign that type to the definition of foo shown above.
So, what we can actually do in Haskell?
One option could be to abuse type classes. There is a way in Haskell to create a kind of "variadic" function exploiting some kind-of convoluted type class machinery. That would make
calc 1 "+" 1 "+" 10 "-" 7 :: Int
type-check and evaluate to the wanted result. I'm not attempting that: it's complex and "hackish", at least in my eye. This hack was used to implement printf in Haskell, and it's not pretty to read.
Another option is to create a custom data type and add some infix operator to the calling syntax. This also exploits some advanced feature of Haskell to make everything type check.
{-# LANGUAGE GADTs, FunctionalDependencies, TypeFamilies, FlexibleInstances #-}
data R t where
I :: Int -> R String
F :: (Int -> Int) -> R Int
instance Show (R String) where
show (I i) = show i
type family Other a where
Other String = Int
Other Int = String
(#) :: R a -> a -> R (Other a)
I i # "+" = F (i+) -- equivalent to F (\x -> i + x)
I i # "-" = F (i-) -- equivalent to F (\x -> i - x)
F f # i = I (f i)
I _ # s = error $ "unsupported operator " ++ s
main :: IO ()
main =
print (I 1 # "+" # 1 # "+" # 10 # "-" # 7)
The last line prints 5 as expected.
The key ideas are:
The type R a represents an intermediate result, which can be an integer or a function. If it's an integer, we remember that the next thing in the line should be a string by making I i :: R String. If it's a function, we remember the next thing should be an integer by having F (\x -> ...) :: R Int.
The operator (#) takes an intermediate result of type R a, a next "thing" (int or string) to process of type a, and produces a value in the "other type" Other a. Here, Other a is defined as the type Int (respectively String) when a is String (resp. Int).
I am learning Haskell and recursion and different types in Haskell is making my brain hurt. I am trying to create a recursive function that will take a 32 bit binary number string and convert it to a decimal number. I think my idea for how the recursion will work is fine but implementing it into Haskell is giving me headaches. This is what I have so far:
bin2dec :: String -> Int
bin2dec xs = ""
bin2dec (x:xs) = bin2dec xs + 2^(length xs) * x
The function is supposed to take a 32 bit number string and then take off the first character of the string. For example, "0100101010100101" becomes "0" and "100101010100101". It then should turn the first character into a integer and multiply it by 2^length of the rest of the string and add it to the function call again. So if the first character in the 32 bit string is "1" then it becomes 1 * 2^(31) + recursive function call.
But, whenever I try to compile it, it returns:
traceProcP1.hs:47:14: error:
* Couldn't match type `[Char]' with `Int'
Expected: Int
Actual: String
* In the expression: ""
In an equation for `bin2dec': bin2dec xs = ""
|
47 | bin2dec xs = ""
| ^^
traceProcP1.hs:48:31: error:
* Couldn't match expected type `Int' with actual type `Char'
* In the second argument of `(+)', namely `2 ^ (length xs) * x'
In the expression: bin2dec xs + 2 ^ (length xs) * x
In an equation for `bin2dec':
bin2dec (x : xs) = bin2dec xs + 2 ^ (length xs) * x
|
48 | bin2dec (x:xs) = bin2dec xs + 2^(length xs) * x
| ^^^^^^^^^^^^^^^^^^
I know this has to do with changing the datatypes, but I am having trouble type casting in Haskell. I have tried type casting x with read and I have tried making guards that will turn the '0' into 0 and '1' into 1, but I am having trouble getting these to work. Any help would be very appreciated.
There is no casting. If you want to convert from one type to another, there needs to be a function with the right type signature to do so. When looking for any function in Haskell, Hoogle is often a good start. In this case, you're looking for Char -> Int, which has several promising options. The first one I see is digitToInt, which sounds about right for you.
But if you'd rather do it yourself, it's quite easy to write a function with the desired behavior, using pattern matching:
bit :: Char -> Int
bit '0' = 0
bit '1' = 1
bit c = error $ "Invalid digit '" ++ [c] ++ "'"
This is a homework, so I would prefer only tips or a link to where I can learn rather than a full answer. This is what I am given:
allEqual :: Eq a => a -> a -> a -> Bool
What I understand from this is that I am supposed to compare 3 values (in this case a, a, a?) and return whether or not they all equal one another. This is what I tried:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z do
Bool check <- x == y
Bool nextC <- y == z
if check == nextC
then True
else False
I honestly feel completely lost with Haskell, so any tips on how to read functions or declare them would help immensely.
This question already has several other perfectly good answers explaining how to solve your problem. I don’t want to do that; instead, I will go through each line of your code, progressively correct the problems, and hopefully help you understand Haskell a bit better.
First, I’ll copy your code for convenience:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z do
Bool check <- x == y
Bool nextC <- y == z
if check == nextC
then True
else False
The first line is the type signature; this is already explained well in other answers, so I’ll skip this and go on to the next line.
The second line is where you are defining your function. The first thing you’ve missed is that you need an equals sign to define a function: function definition syntax is functionName arg1 arg2 arg3 … = functionBody, and you can’t remove the =. So let’s correct that:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z = do
Bool check <- x == y
Bool nextC <- y == z
if check == nextC
then True
else False
The next error is using do notation. do notation is notorious for confusing beginners, so don’t feel bad about misusing it. In Haskell, do notation is only used in specific situations where it is necessary to execute a sequence of statements line by line, and especially when you have some side-effect (like, say, printing to the console) which is executed with each line. Clearly, this doesn’t fit here — all you’re doing is comparing some values and returning a result, which is hardly something which requires line-by-line execution. So let’s get rid of that do:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z =
let Bool check = x == y
Bool nextC = y == z
in
if check == nextC
then True
else False
(I’ve also replaced the <- binding with let … in …, since <- can only be used within a do block.)
Next, another problem: Bool check is not valid Haskell! You may be familiar with this syntax from other languages, but in Haskell, a type is always specified using ::, and often with a type signature. So I’ll remove Bool before the names and add type signatures instead:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z =
let check :: Bool
check = x == y
nextC :: Bool
nextC = y == z
in
if check == nextC
then True
else False
Now, at this point, your program is perfectly valid Haskell — you’ll be able to compile it, and it will work. But there’s still a few improvements you can make.
For a start, you don’t need to include types — Haskell has type inference, and in most cases it’s fine to leave types out (although it’s traditional to include them for functions). So let’s get rid of the types in the let:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z =
let check = x == y
nextC = y == z
in
if check == nextC
then True
else False
Now, check and nextC are only used in one place — giving them names doesn’t do anything, and only serves to make the code less readable. So I’ll inline the definitions of check and nextC into their usages:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z =
if (x == y) == (y == z)
then True
else False
Finally, I see you have an expression of the form if <condition> then True else False. This is redundant — you can simply return the <condition> with the same meaning. So let’s do that:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z = (x == y) == (y == z)
This is much, much better than the code you started with!
(There is actually one more improvement that you can make to this code. At this point, it should be obvious that your code has a bug. Can you find it? And if so, can you fix it? Hint: you can use the && operator to ‘and’ two booleans together.)
Lets start with a function that takes a single Int:
allEqual1Int :: Int -> Bool
allEqual1Int x = True
allEqual1Int' :: Int -> Bool
allEqual1Int' x =
if x == x
then True
else False
If we compare that to your line
allEqual x y z do
we notice that you miss a = and that you don't need a do.
A version for String could look like
allEqual1String' :: String -> Bool
allEqual1String' x =
if x == x
then True
else False
and we observe that the same implementation works for multiple types (Int and String) provided they support ==.
Now a is a type variable, think of it as a variable such that its value is a type. And the requirement that the given type supports == is encoded in the Eq a constraint (Think of it as an interface). Therefore
allEqual :: Eq a => a -> a -> a -> Bool
works for any such type that supports ==.
Haskell is a bit strange language for those who programmed in different languages before. Let's first have a look at this function:
allEqual :: Int -> Int -> Int -> Bool
You can look at this like that: the last "thing" after "->" is a return type. Previews "things" are parameters. From that, we know the function accepts three parameters that are Int and returns the Bool.
Now have a look at your function.
allEqual :: Eq a => a -> a -> a -> Bool
There is an extra syntax "Eq a =>". What it basically does is all the following "a" in declaration must implement Eq. So it is a more generalized version of the first function. It accepts three parameters that implement "Eq" and returns Bool. What the function should probably do is check if all values are equal.
Now let's have a look at your implementation. You are using a do syntax. I feel like it is not the best approach in the beginning. Let's implement a very similar function which checks if all parameters are equal to 3.
allEq3 :: Int -> Int -> Int -> Bool
allEq3 x y z = isEq3 x && isEq3 y && isEq3 z
where
isEq3 :: Int -> Bool
isEq3 x = x == 3
Like in your example, we have three parameters, and we return Bool. In the first line, we call function isEq3 on all the parameters. If all these calls return true allEq3 will also return true. Otherwise, the function will return false. Notice that the function isEq3 is defined below after the keyword "where". This is a very common thing in Haskell.
So what we did here is taking a big problem of checking if all the parameters are equal to 3 and divide it into smaller pieces which check whether a value is equal to 3.
You can improve this implementation a lot but I think this is the best way to take the first steps in Haskell. If you really want to learn this language you should have a look at this.
allEqual :: Eq a => a -> a -> a -> Bool
The signature says: allEqual consumes 3 values of type a; it produces a result of type Bool. The Eq a => part limits the possible operations a can have; it says whatever type a is, it needs to satisfy the requirements defined in Eq. You can find those requirements here: http://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#t:Eq
You now know what operations a can do, you can then complete your function by following the type signature.
Here's how you do it:
allEqual :: Eq a => a -> a -> a -> Bool
allEqual x y z = x == y && y == z
What does this mean?
The first line defines the function's type signature.
In human words, it would say something like:
There is a function called allEqual for any type a. It requires an instance of Eq a* and takes three parameters, all of type a, and returns a Bool
The second line says:
The function allEqual, for any parameters x, y, and z, should evaluate x == y && y == z, which simply compares that x equals y and y equals z.
* Instances or type classes are a language feature that not many other programming languages have, so if you're confused to what they mean I'd suggest learning about them first.
Can somebody point me to how to feed data to:
twice f x = f (f x)
It's taken from Erik Meijer's lecture, and I have the feeling I can only truely understand when passing data to it. Now this only results in errors.
The derived type signature is (t -> t) -> t -> t. Pass any arguments that match and you won't get compiler errors. One example is twice (+1) 0.
The main mistake here is disregarding the type of twice. In Haskell types are very important, and explain precisely how you would call such a function.
twice :: (a -> a) -> a -> a
So, the function works in this way:
the caller chooses any type a they want
the caller passes a function f of type a -> a
the caller passes an argument of type a
twice finally produces a value of type a
Hence, we could do the following. We can choose, for instance, a = Int. Then define the function f as
myFun :: Int -> Int
myFun y = y*y + 42
then choose x :: Int as 10. Finally, we can make the call
twice myFun 10
Alternatively, we can use a lambda and skip the function definition above
twice (\y -> y*y + 42) 10
For illustration here are three functions called erik1, erik2, and erik3 with the same type signature.
erik1, erik2, erik3 ::(a -> a) -> a -> a
erik1 f x = f x
erik2 f x = f(f x) -- Equivalent to "twice"
erik3 f x = f(f(f x))
These eriks take two arguments, the first being a function and the second being a number. Let's choose sqrt as the function and the number to be 16 and run the three eriks. Here's what you get:
*Main> erik1 sqrt 16
4.0
*Main> erik2 sqrt 16
2.0
*Main> erik3 sqrt 16
1.4142135623730951
There are many things you can try, such as erik3 (/2) 16 = 2,because the f in the function allows you to use any appropriate function. In the particular case of sqrt, erik3 is equivalent to this statement in C:
printf ("Eighth root of 16 = %f \n", sqrt(sqrt(sqrt(16))));
Dr. Meijer Ch 7 1:48 to 3:37
As I watched this lecture last night a key point was made when Erik wrote the type signature as twice :: (a -> a) -> (a -> a) and said, "twice is a function that takes a to a and returns a new function from a to a, and by putting some extra parens it becomes painfully obvious that twice is a higher order function."
A C example that comes closer to illustrating that is:
#define eighthRoot(x) (sqrt(sqrt(sqrt(x))))
printf ("eigthtRoot(16) = %f \n", eighthRoot(16));
Given a higher-order function like the following:
let call (f : unit -> 'a) = f()
And another function:
let incr i = i + 1
Is there a way to pass incr to call, without using a lambda: (fun () -> incr 1)?
Obviously, passing (incr 1) does not work, as the function is then "fully applied."
EDIT
To clarify: I'm wondering if there's a way to curry a function, such that it becomes a function: unit -> 'a.
You can define such a shortcut yourself:
let ap f x = fun () -> f x
call (ap incr 1)
If the function you want to transform happens to be a pure function, you can define the constant function instead:
let ct x _ = x (* const is reserved for future use :( *)
call (ct (incr 1))
It looks more like an attempt to add laziness to strict F# then some kind of currying.
And in fact there is a built in facility for that in F#: http://msdn.microsoft.com/en-us/library/dd233247.aspx - lazy keyword plus awkward Force:
Not sure if it's any better than explicit lambda, but still:
let incr i =
printf "incr is called with %i\n" i
i+1
let call (f : unit -> 'a) =
printf "call is called\n"
f()
let r = call <| (lazy incr 5).Force
printf "%A\n" r