Haskell constants in functions - haskell

I was wondering if someone could explain to me what (-2)(-2) in the brackets in the first line of the code stand for. I am new to Haskell and I’m trying to understand.
to_up_left board (x, y, t, c) (-2)(-2) = to_up_left board (x, y, t, c) x y
to_up_left board (x, y, t, c) 0 _ = []
to_up_left board (x, y, t, c) _ 9 = []
to_up_left board ((-1), y, t, c) _ _ = []
to_up_left board (x, y, t, c) _x _y = if (empty_field board (_x-1) (_y+1)) && (t == 'a' || t == 'A' )
then concat [decode_x x ++ decode_y y ++ "-" ++ decode_x (_x-1) ++ decode_y (_y+1)]: to_up_left board (x, y, t, c) (_x-1) (_y+1)
else if (friend_on_field board (_x-1) (_y+1)) && (t == 'a' || t == 'A' )
then concat [decode_x x ++ decode_y y ++ "-" ++ decode_x (_x-1)++ decode_y (_y+1)]: []
else []

if someone could explain to me what (-2) (-2) in the brackets in the first line of the code stand for.
This is to pattern match with negative numbers, otherwise it will be interpreted as
(to_up_left board (x, y, t, c)) - (2 (-2))
and it thus seems that you are defining a (-) function. Negative numbers should thus be specified between parenthesis. The parenthesis have no special meaning: you can nest it an arbitrary number of times ((-2)) for example.

The function to_up_left has 4 arguments. In the top line:
board is the first argument
(x, y, t, c) is the second argument
(-2) is the third argument
(-2) is the fourth argument.
The (-2) arguments need their parentheses because otherwise - would act as a binary operator.
Haskell function definitions do pattern matching:
board names its argument, just as in C-like languages
(x,y,t,c) expects a 4-tuple, and binds the 4 elements to separate names
(-2) checks to see if the argument is equal to -2
if the third and fourth arguments are not both -2, try the next pattern

Related

How can I return the primitive data type from polymorphism?

Given some custom sum data type,
data Type = Thing Char | NotThing Char
How can I use == to compare between the Char here and some other Char? As below:
let f = 'a'
NotThing e == f
>>> True
Of course, this code cannot compare between types as NotThing is a separate type to Char.
If x :: Char and y :: Type, then the following expressions (among others) are well-typed:
y == Thing x
y == NotThing x
y `elem` [Thing x, NotThing x]
case y of { Thing x' -> x == x'; NotThing x' -> x == x' }
Probably the last one is closest to what you want. I would abstract slightly and write
extract :: Type -> Char
extract (Thing x') = x'
extract (NotThing x') = x'
because I would expect that to occasionally be useful in other contexts. With that in hand, the following expression is also well-typed:
extract y == x
Of course, you'll want to pick a better name than extract, just like you'll do for Type, Thing, and NotThing.

Haskell way to joint two small functions. Syntax advice needed

I'm new to Haskell and I'm having kind of a hard time joining two sections of code for this program. What it does (or should do) is to let me know if a triangle is isosceles by the theorem of cosenes. Here it is what I thought would work:
--Determine if a triangle is isosceles by the cosene theroem
module Main where
sides :: (Float, Float, Float) -> (Float, Float, Float)
sides (a, b, c) = (x, y, z)
where
x = acos((b^2 + c^2 - a^2) / (2 * b * c))
y = acos((a^2 + c^2 - b^2) / (2 * a * c))
z = acos((a^2 + b^2 - c^2) / (2 * a * b))
theorem :: (Float, Float, Float) -> String
theorem (x, y, z)
|(x==y && x/=z) = "Es isosceles"
|(x==z && x/=y) = "Es isosceles"
|(y==z && y/=x) = "No es isosceles"
main :: IO()
main = do
print "Please type the size of the triangle faces: "
(a, b, c) <- getLine
(x, y, z) <- sides (a, b, c)
string <- theorem(x, y, z)
print string
I'm not sure that after my advice updated code will run, but I see some problems in this code:
print isn't exactly what you want, because strings will be printing with quotes ("Please type the size of the triangle faces: " instead Please type the size of the triangle faces: ). If you want print a string, replace print to putStrLn
getLine has type IO String, so pattern matching with (a, b, c) will be failed. But you can write read <$> getLine - it will apply function read which convert a string to a value of any readable type (in this case it is (Float, Float, Float)) to the input string. But the input string must be in format (_, _, _) (for example (1, 1, 1))
when you write a <- b in do-block, it means that b has type m t where m is Monad, and a has type t. sides has type (Float, Float, Float) -> (Float, Float, Float), so you can't write this instead b in the expression above. But you can write let a = b where both a and b has the same type t. So you can write let (x, y, z) = sides (a, b, c) instead (x, y, z) <- sides (a, b, c). Similarly with string <- theorem(x, y, z)
theorem don't defined for all values (x, y, z) because you consider cases with the pair of equals value and one not equal

Generic transformations on a set of a given datatype

If I have a datatype representing a subset of propositional logic such as
data Prop = Lit String
| Neg Prop
| And Prop Prop
| Or Prop Prop
Are there then easy ways to do generic transformations on [[Prop]]? E.g.
replace [[And a b, c]] with [[a, b, c]]
replace [[Or a b, c]] with [[a], [b], [c]], or
removing occurrences of sublists containing both Neg a and a, e.g. turning [[Neg a, x, a], [b]] into [[b]]
This feels like something close to what e.g. uniplate does, but “two levels up”.
I assume that your second rule is wrong, and you really meant to say either:
replace [[Or a b],[c]] with [[a],[b],[c]]
or else:
replace [[Or a b, c]] with [[a,c],[b,c]]
In other words, I assume you're trying to convert a Prop into an alternate representation [[Prop]] where the first-level list is an "or" and the second-level lists are "and"s, with all terms being either literals or Neg-literals. So, you're trying to imagine how you could apply a bunch of generic structural rules to make transformations like:
[[And a (Or b c)]]
[[a, Or b c]] -- apply "And" rule
[[a,b],[a,c]] -- apply some kind of "Or" distribution rule
If so, having generic transformations isn't much use. With your current datatype, you can only apply these transformations to top-level expressions anyway. For example, there's no obvious way to apply an Or rule here:
[[And a (And b (Or c d))]]
without first applying And rules a couple of times. If you change your data type to add, say, an L2 [[Prop]] constructor, so you can transform the above expression to:
[[And a (And b (L2 [[c],[d]]))]] -- apply "Or" rule
it's not clear what that buys you.
Ultimately, I don't think this is the right approach...
You have a perfectly adequate representation of your prepositional logic in the Prop data type; and you have a desired final representation. Instead of trying to translate your Prop representation into the final representation using piecemeal generic transformations, transform your Prop representation using standard recursive Prop-to-Prop transformations into a canonical Prop form, and do the translation as the final step.
Here, a reasonable canonical form is:
Or e1 (Or e2 (... (Or e3 e4)))
where each ek is of form:
And t1 (And t2 (... (And t3 t4)))
and each tk is either a Lit _ or a Neg (Lit _). Obviously, this canonical form can be translated pretty easily into the desired final representation as a [[Prop]].
I've included a possible solution below. I don't see that much opportunity for simplifying things via generic transformations. Most of the pattern matching seems to be doing non-trivial work.
Possible Solution
After a bit of preamble:
import Data.List
data Prop = Lit String
| Neg Prop
| And Prop Prop
| Or Prop Prop
deriving (Eq)
then one way to translate an arbitrary Prop into this canonical form is to first push all the Negs down to the literal terms:
pushNeg :: Prop -> Prop
pushNeg = push False
where
-- de Morgan's laws
push neg (And x y) = (if neg then Or else And) (push neg x) (push neg y)
push neg (Or x y) = (if neg then And else Or) (push neg x) (push neg y)
-- handle Neg and Lit
push neg (Neg y) = push (not neg) y
push neg (Lit l) = if neg then Neg (Lit l) else Lit l
then push all the Ands down on top of them. This is tougher to get right, but I think the following is correct, even though it does a bit of unnecessary work in some cases:
pushAnd :: Prop -> Prop
pushAnd (Or x y) = Or (pushAnd x) (pushAnd y)
pushAnd (And x y)
= let x' = pushAnd x
in case x' of
Or u v -> Or (pushAnd (And u y)) (pushAnd (And v y))
_ -> let y' = pushAnd y
in case y' of
Or u v -> Or (pushAnd (And x' u)) (pushAnd (And x' v))
_ -> And x' y'
pushAnd x = x
and then recursively make all the And and Or clauses right-associative:
rassoc :: Prop -> Prop
rassoc (Or (Or x y) z) = rassoc (Or x (Or y z))
rassoc (Or x z) = Or (rassoc x) (rassoc z)
rassoc (And (And x y) z) = rassoc (And x (And y z))
rassoc (And x z) = And x (rassoc z)
rassoc x = x
and finally convert the canonical form to its final representation (dropping the inconsistent clauses and duplicate terms while we're at it):
translate :: Prop -> [[Prop]]
translate = nub . map nub . filter consistent . doOr
where
doOr x = case x of
Or x y -> doAnd x : doOr y
x -> doAnd x : []
doAnd x = case x of
And x y -> x : doAnd y
x -> x : []
consistent lits =
let (falses, trues) = partition isNeg lits
falses' = map (\(Neg (Lit l)) -> l) falses
trues' = map (\ (Lit l) -> l) trues
in null (intersect falses' trues')
isNeg (Neg x) = True
isNeg _ = False
The whole pipeline is:
final :: Prop -> [[Prop]]
final = translate . rassoc . pushAnd . pushNeg
and here's some test code:
a = Lit "a"
b = Lit "b"
c = Lit "c"
d = Lit "d"
e = Lit "e"
-- Show instance, but only for `final` forms
instance Show Prop where
show (Lit x) = x
show (Neg (Lit x)) = '~':x
main :: IO ()
main = do print $ final (Neg a)
print $ final (Or a b)
print $ final (Or a a)
print $ final (And a b)
print $ final (And (Or (And (Or a b) c) d) e)
print $ final (And (Or (Or a b) c) (Neg (And a (Or b d))))
which outputs:
[[~a]]
[[a],[b]]
[[a]]
[[a,b]]
[[a,c,e],[b,c,e],[d,e]]
[[a,~b,~d],[b,~a],[c,~a],[c,~b,~d]]
There's still some opportunity for further simplification, as:
final (And a (Or a b))
gives final form [[a],[a,b]] instead of just [[a]].

Comparing Bool Value in Matrix

t = True
f = False
anzNachbarn :: [[Bool]] -> (Integer,Integer) -> Integer
anzNachbarn a (x,y)
| x < 0 || y < 0=-1
| otherwise ... here comes the comparison
This is an example matrix:
[[True,False,False],
[True,False,False],
[False,True,False]]
here i need an algorithm, where it calculates (for given x and y position in matrix) its neighbours (only "true" neighboors) and increase it by 1 for each true neighboor.
For example: anzNachbarn [[True,False,False],[True,False,False],[False,True,False]] (0,1)
returns 2 back.
:Edit
I still have a question how can I now implement each component of the result matrix, the number of named elements with True neighboring fields indicates the corresponding component of the argument matrix Applies to
[[True, False, False],
[True, False, False],
[False, True , False]]
the function func returns the results matrix [[1,2,0], [2,3,1], [2,1,1]]
with signature func :: [[Bool]] -> [[Integer]]
have you got any idea about this ?
You almost certainly want to use an array (from Data.Array) in this situation, since looking up an item in a list by its index is very slow.
Here's a quick implementation using Array:
countNeighbors :: Array (Int, Int) Bool -> (Int, Int) -> Int
countNeighbors board (x, y) = length
[ (x', y')
| x' <- [x - 1, x, x + 1]
, y' <- [y - 1, y, y + 1]
, x' /= x || y' /= y
, inRange (bounds board) (x', y')
, board ! (x', y')
]
This is a list comprehension with two generators and three guards. The generators simply give us the indices of the nine positions in a three-by-three square centered at (x, y) (you'll need a minor change if you don't want neighbors at the corners to be considered).
The first guard (x' /= y') ignores (x, y) itself. The second throws out positions that aren't within the bounds of the array. The final guard throws out positions that are in the array but have a False value.
So we now have a list of indices for the neighbors with True values. The length of this list is the desired count.
This is ugly, but seems to work...
anzNachbarn :: [[Bool]] -> (Int,Int) → Integer
anzNachbarn a (x,y)
| x < 0 || y < 0 = -1
| otherwise = sum [v x' y' | x' <- [max 0 (x-1)..x+1],
y' <- [max 0 (y-1)..y+1],
x ≠ x' || y ≠ y' ]
where v i j = if j >= length a
|| i >= length (a !! 0)
|| not (a !! j !! i)
then 0 else 1
[Edit]
In order to convert the whole array, you can write the equally ugly
conv a = [line y | y <- [0 .. (length a) - 1]]
where line y = [anzNachbarn a (x,y) | x <- [0 .. ((length (a !! 0) - 1)]]
Note that the performance of this is terrible.

How to recursively compare the digits in a number in Haskell

I am doing problem 112 on Project Euler and came up with the following to test the example case (I'll change the number in answer to 0.99 to get the real answer):
isIncre x | x == 99 = False
| otherwise = isIncre' x
where
isIncre' x = ???
isDecre x = isIncre (read $ reverse $ show x :: Int)
isBouncy x = (isIncre x == False) && (isDecre x == False)
bouncers x = length [n|n<-[1..x],isBouncy n]
nonBouncers x = length [n|n<-[1..x],(isBouncy n) == False]
answer = head [x|x<-[1..],((bouncers x) / (nonBouncers x)) == 0.5]
But what I don't know how to do is define a function isIncre' which tests to see if the digits in a number are greater than or equal to the one on their left. I know it needs to be done recursively but how?
On a side note, I know I can only use / on two floating point numbers but how can I make the output of bouncers to be floating point number instead of an integer?
Edit:
Thanks for the help, but it didn't like the = when I changed isIncre to:
isIncre x | x <= 99 = False
| otherwise = isIncre' (mshow x)
where
isIncre' (x:y:xs) = (x <= y) && (isIncre' (y:xs))
isIncre' _ = True
The number 0.99 cannot be represented exactly in base 2. Hence you may want to avoid the use of floating point numbers for this assignment. Instead, to see whether exactly 99% of the numbers <= x are bouncers, test whether
100 * (x - bouncers x) == x
This works because it is (mathematically) the same as (x - bouncers x) == x / 100, which is true if (x - bouncers x) (the number of non-bouncy numbers) is 1% of x. Observe that there is thus no need to define nonBouncers.
Also, another way to define bouncers is
bouncers x = length $ filter isBouncy [1..x]
However, you should reconsider your design. Currently you are recalculating the number of bouncy numbers up to x, for every x that you try. So a lot of work is being done over and over. What you may instead want to do, is generate a sequence of tuples (x, n), where n is the number of bouncy numbers <= x. Observe that if there are n bouncy numbers <= x, then there are either n or n + 1 bouncy number <= x + 1.
More specifically, to calculate (x + 1, n'), all you need is (x, n) and the output of isbouncy (x + 1).
If you have a string representation of an integer number, you could write the isIncre function like this (ord converts a character to an integer and string is just a list of chars):
isIncre (x:y:xs) = ord x <= ord y && isIncre (y:xs)
isIncre _ = True
It could be even nicer to write the isIncre function without ord, working on any ordered type, then combine it with "map ord" when you call it instead. The implementation would then be just:
isIncre (x:y:xs) = x <= y && isIncre (y:xs)
isIncre _ = True
That could be called like this, if x is an integer number
isIncre (map ord (show x))
I would use really nice functional version of isIncre if you have string representation of intetger.
isIncre :: (Ord a) => [a] -> Bool
isIncre list = and $ zipWith (<=) list (tail list)
If not, just compose it with show.
isIncreNum :: Integer -> Bool
isIncreNum = isIncre . show

Resources