I am currently working on a chessgame in Haskell. Here is my function that evaluates to True, when you feed it the right parameters for castling on the kingsside. (the problem is in part 1 & 2, look at the comments). I tried to use function composition to find a more concise solution, but it didn't really work out for me. I'd be glad if someone could take a glance at what i did and explain where i went wrong ... thanks a lot in advance
shortCastlingWhite :: Int -> Int -> GameState -> Bool
shortCastlingWhite start end state@(board,_) =
(board !! 95 == 10) && -- on 95=(e,1) is a white King
(board !! 98 == 11) && -- on 98=(h,8) is a white Rook
(start == 95 && end == 97) && -- move from (e,1) to 97=(g,1)
(not $ (wasMoved state 95 || wasMoved state 98) && -- King and Tower weren't moved until now
(not $ (indexOccupied 96 state || -- part 1 !! 96=(f,1) and (g,1) are unoccupied
(indexOccupied 97 state) || -- part 1
(isThreatenedBy Black 95 state) || -- part 2 !! neither (e,1) nor (f,1) or (g,1) are threatened by Black Figures
(isThreatenedBy Black 96 state) || -- part 2
(isThreatenedBy Black 97 state))) -- part 2
here are the typesignatures for the used functions
isThreatenedBy :: Colour -> GameState -> Int -> Bool
wasMoved :: GameState -> Int -> Bool
i wanted to rewrite the very verbose parts 1 and 2 as :
all (swap indexUnoccupied state) [96,97] &&
(all ((not.isThreatenedBy) Black state) [95,96,97]) &&
(all ((not.wasMoved) state) [95,98])
where swap f a b = f b a
--
but i cant get around the errormessage of :
newchess.hs:240:181:
Couldn't match expected type `GameState -> a0 -> Bool`
with actual type `Bool`
The function `not . isThreatenedBy` is applied to two arguments,
but its type `Colour -> Bool` has only one
In the first argument of `all`, namely
`((not . isThreatenedBy) Black state)`
In the first argument of `(&&)', namely
`(all ((not . isThreatenedBy) Black state) [95, 96, 97])`
isThreatenedBy :: Colour -> GameState -> Int -> Bool
when i compose not and isThreatenedBy i should get
a function f = (not . isThreatenedBy)
of type
f :: Colour -> GameState -> Int -> Bool
but really i get something like Colour -> Bool
i think.
Then i partially apply it with values of Colour and GameState
and the resulting function f' should be of type
f' :: Int -> Bool
and then i kinda map it over the list [95,96,97]
and see
if every element satisfies f'
via all
or so was the plan ...
newchess.hs:240:186:
Couldn't match type `GameState -> Int -> Bool` with `Bool`
Expected type: Colour -> Bool
Actual type: Colour -> GameState -> Int -> Bool
Probable cause: `isThreatenedBy` is applied to too few arguments
In the second argument of `(.)`, namely `isThreatenedBy`
In the expression: not . isThreatenedBy
its odd that (not . wasMoved) is applied to too many arguments in error1 and probably to too few in error 2 , but i cant move the list elements inside the brackets , otherwise i could just go back to the point from that i started
newchess.hs:240:238:
Couldn't match expected type `a1 -> Bool` with actual type `Bool`
Possible cause: `not . wasMoved` is applied to too many arguments
In the first argument of `all`, namely `((not . wasMoved) state)`
In the second argument of `(&&)`, namely
`(all ((not . wasMoved) state) [95, 98])`
same as above in error 1 (just this time with wasMoved)
newchess.hs:240:243:
Couldn't match type `Int -> Bool' with `Bool`
Expected type: GameState -> Bool
Actual type: GameState -> Int -> Bool
Probable cause: `wasMoved` is applied to too few arguments
In the second argument of `(.)`, namely `wasMoved`
In the expression: not . wasMoved
Failed, modules loaded: none.
as in error 2 i think
I might have misunderstood this one a bit, but have a look at this. This does NOT work:
Prelude> let f = (abs . (+))
<interactive>:11:5:
Non type-variable argument in the constraint: Num (a -> a)
(Use FlexibleContexts to permit this)
When checking that ‘f’ has the inferred type
f :: forall a. (Num a, Num (a -> a)) => a -> a -> a
It does not type check. The reason for this is the fact that the (.)
function takes two functions as parameters, where those two functions take one parameter each. In this example the (+)
function takes two parameters and is thus of the wrong type. This works:
Prelude> let f = (abs . (+ 3))
Because I turned the function into a function that takes only one parameter. Your isThreatenedBy
function could be changed the same way:
(all (not . (isThreatenedBy Black state)) [95,96,97])
Not sure if that was really you root problem, but try it out.