check if a tree is complete standard ml - function

I want to make a function in standard ml that checks if a tree is complete or not, the function somehow works, but its giving me the wrong type and a warning of non-exhaustive cases
The tree code:
datatype 'data tree =
EMPTY
| NODE of 'data tree * 'data * 'data tree;
fun isComplete EMPTY = true
| isComplete (NODE(x, y, z)) = if (x = EMPTY andalso z <> EMPTY) orelse (x <> EMPTY andalso z = EMPTY) then false else true;
Now the above function's type is: ''a tree -> bool but the required type is 'a tree -> bool
The warning I'm having is:
stdIn:169.8 Warning: calling polyEqual
stdIn:169.26 Warning: calling polyEqual
stdIn:169.45-169.47 Warning: calling polyEqual
stdIn:169.64-169.66 Warning: calling polyEqual
stdIn:124.1-169.94 Warning: match nonexhaustive
NODE (x,y,z) => ...
What is the problem I'm having?
EDIT:
Thanks to Michael, I fixed the code and now it works:
- fun isComplete EMPTY = true
| isComplete (NODE(EMPTY, _, EMPTY)) = true
| isComplete (NODE(NODE(x, y, z), _, NODE(a, b, c))) = true
| isComplete (EMPTY, _, NODE(x, y, z)) = false
| isComplete (NODE(x, y, z), _, EMPTY) = false;

The ''a tree -> bool type indicates that a is an equality type: it must be a type that supports testing with equals. Since you are using = and <> to test x and z, the tree data must support equality (even though you're not doing anything interesting with the values). This is the root of the polyEqual warning.
The nonexhaustive match warning is more puzzling. When I paste your datatype and function definitions into Moscow ML, I do not get a warning. I don't think I'd worry about it too much, as I'd expect fixing the type to also take care of the warning.
To get the desired type 'a tree -> bool, I'd suggest getting rid of the if in favor of pattern matching. E.g.:
fun isComplete EMPTY = true
| isComplete (NODE(EMPTY, _, EMPTY)) = true
| isComplete (NODE(EMPTY, _, NODE(x,y,z))) = false
| ... (* fill out the rest of the cases *)
I'll leave it to you to figure out the full set of cases, as this looks like homework.
Incidentally, I don't think your test for completeness is correct. Consider what happens when neither subtree is EMPTY: you call the tree complete without considering the contents. This doesn't have anything to do with the warnings you're seeing, though.

Concerning the polyEqual warning: in SML/NJ this warning is printed everytime you use this operator, but that doesn't mean your code is faulty. Here's a blog post about it, and in the comments someone explains why the warning is given: http://abstractfactory.blogspot.fr/2006/05/sml-hacking-tip-turn-off-polyequal.html

Related

I'm really confused about function declarations in Haskell

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.

Binary to Decimal Conversion in Haskell using Horners Algorithm

I am trying to implement a function here which takes a list of Bool representing binary numbers such as [True, False, False] and convert that into corresponding decimal number according to Horners method.
Function type would be [Bool] -> Int.
Algorithms which i am following is:
Horners Algorithm Visual Explanation:
So far i have implemented the logic in which it says first it will check whether the list is empty or either one element in the list [True], will give 1 and [False] will give 0.
Then in this case binToDecList (x:xs) = binToDecList' x 0 what i did to treat first element whether this is True or False.
binToDecList :: [Bool] -> Int
binToDecList [] = error "Empty List"
binToDecList [True] = 1
binToDecList [False] = 0
binToDecList (x:xs) = binToDecList' x 0
binToDecList' x d | x == True = mul (add d 1)
| otherwise = mul (add d 0)
add :: Int -> Int -> Int
add x y = x + y
mul :: Int -> Int
mul x = x * 2
I want to use the result of binToDecList' in the next iteration calling itself recursively on the next element of the list. How can i store the result and then apply it to next element of the list recursively. Any kind of help would be appreciated.
The type* of foldl tells us how it must work.
foldl :: (b -> a -> b) -> b -> [a] -> b
Clearly [a], the third argument that is a list of something, must be the list of Bool to be handed to Horner’s algorithm. That means the type variable a must be Bool.
The type variable b represents a possibly distinct type. We are trying to convert [Bool] to Int, so Int is a decent guess for b.
foldl works by chewing through a list from the left (i.e., starting with its head) and somehow combining the result so far with the next element from the list. The second argument is typically named z for “zero” or the seed value for the folding process. When foldl reaches the end of the list, it returns the accumulated value.
We can see syntactically that the first argument is some function that performs some operation on items of type b and type a to yield a b. Now, a function that ignores the a item and unconditionally results in whatever the b is would fit but wouldn’t be very interesting.
Think about how Horner’s algorithm proceeds. The numbers at the elbows of the path on your diagram represent the notional “result so far” from the previous paragraph. We know that b is Int and a is Bool, so the function passed to foldl must convert the Bool to Int and combine it with the result.
The first step in Horner’s algorithm seems to be a special case that needs to be handled differently, but foldl uses the same function all the way through. If you imagine “priming the pump” with an invisible horizontal move (i.e., multiplying by two) to begin with, we can make the types fit together like puzzle pieces. It’s fine because two times zero is still zero.
Thus, in terms of foldl, Horner’s algorithm is
horners :: [Bool] -> Int
horners = foldl f 0
where f x b =
let b' = fromEnum b
in 2*x + b'
Notice that 2*x + b' combines subsequent horizontal and vertical moves.
This also suggests how to express it in direct recursion.
horners' :: [Bool] -> Int
horners' [] = 0
horners' l = go 0 l
where -- over then down
go x [] = x
go x (b:bs) =
let b' = fromEnum b
in go (2*x + b') bs
Here the inner go loop is performing the left-fold and combining each next Bool with the result so far in i.
* A pedagogical simplification: the actual type generalizes the list type into Foldable.

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

Returning True for only 1 Function out of the list of 3

Since I'm pretty sure that using global variables in Haskell is frowned upon. I'm wondering is there anyway I can achieve the following?
-- list has elements that are odd
listHasOdd :: [Integer] -> Bool
-- list has elements that are even
listHasEven :: [Integer] -> Bool
--list has a length > 5
longList :: [Integer] -> Bool
-- Maps the function to a [Bool]
-- This function cannot be modified to fix the problem.
checkList :: [Integer] -> [Bool]
checkList xs = map (\ y -> y xs) listChecker
where listChecker = [listHasOdd, listHasEven, longList]
Is there anyway that I can ensure that only one of them returns true?
For example, [1,2,3,5], I would want only want listHasOdd to return
True which is [True, False, False]. (Evaluated from top to bottom).
Another example, [2,4,6,8,10,12,14], the returns should be [False, True, False].
In other words, checkList [1,2,3,5] returns [True, False, False], checkList[2,4,6,8,10,12,14] returns [False, True, False]
**The last function would always be False in my example, since it is unreachable.
I know I can do an if statement to check if the previous one is True but that seems like a pretty dumb idea. Or is that actually the way to do it? (Considering Haskell "remembers" the results of the previous function)
I don't see the point of it, but
foldr foo [] $ map ($ xs) [listHasOdd, listHasEven, longList]
where
foo True zs = True : map (const False) zs
foo False zs = False : zs
would produce the desired result, and it would only evaluate the functions until one of them returned True (or the end of the list of functions is reached).
This is the best I can come up with. It generalises relatively painlessly to handle the number of possible outcomes of a poker hand, for example.
data Outcome
= ListHasOdd
| ListHasEven
| LongList
| Nope
deriving Eq
outcomeFromList :: [Integer] -> Outcome
outcomeFromList xs
| any odd xs = ListHasOdd
| any even xs = ListHasEven
| 5 < length xs = LongList
| otherwise = Nope
listHasOdd = (ListHasOdd ==) . outcomeFromList
listHasEven = (ListHasEven ==) . outcomeFromList
longList = (LongList ==) . outcomeFromList
But even this is stupid: instead of generating a [Bool], why not just use the Outcome directly?
Edit: Or we could pay attention to what the functions mean.
listHasOdd xs = any odd xs
listHasEven [] = False
listHasEven xs = all even xs
-- if not all of them are even, then at least one must be odd,
-- and `listHasOdd` would give `True`
longList _ = False
-- if the list has at least 5 elements,
-- then either the list has at least one odd element
-- (and `listHasOdd` would give `True`)
-- or the list has at least five even elements
-- (and `listHasEven` would give `True`)

returning two different types from one function

How can I return values of multiple types from a single function?
I want to do something like:
take x y | x == [] = "error : empty list"
| x == y = True
| otherwise = False
I have a background in imperative languages.
There is a type constructor called Either that lets you create a type that could be one of two types. It is often used for handling errors, just like in your example. You would use it like this:
take x y | x == [] = Left "error : empty list"
| x == y = Right True
| otherwise = Right False
The type of take would then be something like Eq a => [a] -> [a] -> Either String Bool. The convention with Either for error handling is that Left represents the error and Right represents the normal return type.
When you have an Either type, you can pattern match against it to see which value it contains:
case take x y of
Left errorMessage -> ... -- handle error here
Right result -> ... -- do what you normally would
There is several solutions to your problem, depending on your intention : do you want to make manifest in your type that your function can fail (and in this case do you want to return the cause of the failure, which may be unnecessary if there is only one mode of failure like here) or do you estimate that getting an empty list in this function shouldn't happen at all, and so want to fail immediately and by throwing an exception ?
So if you want to make explicit the possibility of failure in your type, you can use Maybe, to just indicate failure without explanation (eventually in your documentation) :
take :: (Eq a) => [a] -> [a] -> Maybe Bool
take [] _ = Nothing
take x y = x == y
Or Either to register the reason of the failure (note that Either would be the answer to "returning two types from one function" in general, though your code is more specific) :
take :: (Eq a) => [a] -> [a] -> Either String Bool
take [] _ = Left "Empty list"
take x y = Right $ x == y
Finally you can signal that this failure is completely abnormal and can't be handled locally :
take :: (Eq a) => [a] -> [a] -> Bool
take [] _ = error "Empty list"
take x y = x == y
Note that with this last way, the call site don't have to immediately handle the failure, in fact it can't, since exceptions can only be caught in the IO monad. With the first two ways, the call site have to be modified to handle the case of failure (and can), if only to itself call "error".
There is one final solution that allows the calling code to choose which mode of failure you want (using the failure package http://hackage.haskell.org/package/failure ) :
take :: (Failure String m, Eq a) => [a] -> [a] -> m Bool
take [] _ = failure "Empty list"
take x y = return $ x == y
This can mimics the Maybe and the Either solution, or you can use take as an IO Bool which will throw an exception if it fails. It can even works in a [Bool] context (returns an empty list in case of failure, which is sometimes useful).
You can use the error functions for exceptions:
take :: Eq a => [a] -> [a] -> Bool
take [] _ = error "empty list"
take x y = x == y
The three answers you've gotten so far (from Tikhon Jelvis, Jedai and Philipp) cover the three conventional ways of handling this sort of situation:
Use the error function signal an error. This is often frowned upon, however, because it makes it hard for programs that use your function to recover from the error.
Use Maybe to indicate the case where no Boolean answer can be produced.
Use Either, which is often used to do the same thing as Maybe, but can additionally include more information about the failure (Left "error : empty list").
I'd second the Maybe and Either approach, and add one tidbit (which is slightly more advanced, but you might want to get to eventually): both Maybe and Either a can be made into monads, and this can be used to write code that is neutral between the choice between those two. This blog post discusses eight different ways to tackle your problem, which includes the three mentioned above, a fourth one that uses the Monad type class to abstract the difference between Maybe and Either, and yet four others.
The blog entry is from 2007 so it looks a bit dated, but I managed to get #4 working this way:
{-# LANGUAGE FlexibleInstances #-}
take :: (Monad m, Eq a) => [a] -> [a] -> m Bool
take x y | x == [] = fail "error : empty list"
| x == y = return True
| otherwise = return False
instance Monad (Either String) where
return = Right
(Left err) >>= _ = Left err
(Right x) >>= f = f x
fail err = Left err
Now this take function works with both cases:
*Main> Main.take [1..3] [1..3] :: Maybe Bool
Just True
*Main> Main.take [1] [1..3] :: Maybe Bool
Just False
*Main> Main.take [] [1..3] :: Maybe Bool
Nothing
*Main> Main.take [1..3] [1..3] :: Either String Bool
Right True
*Main> Main.take [1] [1..3] :: Either String Bool
Right False
*Main> Main.take [] [1..3] :: Either String Bool
Left "error : empty list"
Though it's important to note that fail is controversial, so I anticipate reasonable objections to this approach. The use of fail here is not essential, though—it could be replaced with any function f :: (Monad m, ErrorClass m) => String -> m a such that f err is Nothing in Maybe and Left err in Either.