2016-03-31 1 views
1

Je travaille actuellement sur un jeu d'échecs à Haskell. Voici ma fonction qui évalue à Vrai, quand vous le nourrissez les bons paramètres pour ronger sur le côté du roi. (le problème est dans la partie 1 & 2, regardez les commentaires). J'ai essayé d'utiliser la fonction de composition pour trouver une solution plus concise, mais ça n'a pas vraiment marché pour moi. Je serais heureux si quelqu'un pourrait prendre un coup d'oeil à ce que je l'ai fait et expliquer où je suis allé mal ... merci beaucoup à l'avanceAppliquer partiellement des fonctions et les composer par la suite

shortCastlingWhite :: Int -> Int -> GameState -> Bool 
shortCastlingWhite start end [email protected](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 

ici sont les typesignatures pour les fonctions utilisées

isThreatenedBy :: Colour -> GameState -> Int -> Bool 
wasMoved :: GameState -> Int -> Bool 

je voulais réécrire les parties très verbeux 1 et 2 comme:

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 
-- 

mais je ne peux pas obtenir autour du errormessage de:

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 :: Couleur -> GameState -> Int -> Bool

quand je compose pas et isThreatenedBy je devrais obtenir une fonction f = (not . isThreatenedBy) de type

f :: Colour -> GameState -> Int -> Bool

mais vraiment je reçois quelque chose comme Colour -> Bool je pense. Puis i appliquer partiellement avec des valeurs de couleur et GameState et la fonction résultante f doit être de type

f' :: Int -> Bool

puis je la carte kinda sur la liste [95,96,97] et voir si tous les éléments satisfait f' via all

ou si le plan était ...

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 

son étrange que (pas. wasMoved) est appliqué à trop d'arguments dans error1 et probablement trop peu dans l'erreur 2, mais je ne peux pas déplacer les éléments de la liste à l'intérieur des crochets, sinon je pourrais revenir au point de que j'ai commencé

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])` 

comme ci-dessus dans l'erreur 1 (juste cette fois avec 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. 

comme erreur 2 je pense que

+0

Notez que ce que vous appelez 'swap' est déjà fourni en tant que fonction' flip'. – Bakuriu

+0

Le nom 'swap' est également" pris "pour' swap :: (a, b) -> (b, a) 'dans' Data.Tuple'. – dfeuer

+0

grâce à vous deux, je ne savais pas que ... mais je vais le garder à l'esprit – Fynn

Répondre

3

je pourrais avoir mal compris celui-ci un peu, mais un coup d'oeil à ce sujet. Cela ne fonctionne PAS:

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 

Il ne vérifie pas de type. La raison en est que la fonction (.) prend deux fonctions en tant que paramètres, où ces deux fonctions prennent un paramètre chacune. Dans cet exemple, la fonction (+) prend deux paramètres et est donc du mauvais type.Cela fonctionne:

Prelude> let f = (abs . (+ 3)) 

Parce que j'ai tourné la fonction dans une fonction qui prend seulement un paramètre. Votre fonction isThreatenedBy pourrait être modifié de la même façon:

(all (not . (isThreatenedBy Black state)) [95,96,97]) 

Je ne sais pas si cela était vraiment racine du problème, mais l'essayer.

+0

Notez également que 'f. g' est équivalent à '\ x -> f (g x)'. Vous * pourriez * (mais ** ne devriez pas **) utiliser '(.). (.) $ f g' pour obtenir l'équivalent de '\ x y -> f (g x y)' ou même '((.). (.)). (.) $ f g' pour obtenir '\ x y z -> f (g x y z)'. Donc, en utilisant '((.). (.)). (.) $ Not isThreatenedBy' devrait fonctionner et ce qui était prévu ... mais éviter cette supercherie. – Bakuriu

+0

cela fonctionne parfaitement, et maintenant je me rends compte de ce que j'ai fait mal je n'appliquais même pas partiellement 'isThreatendBy' correctement parce que je l'ai mis entre parenthèses qui coupé l'application off ... – Fynn

3

Commençons par le prédicat personnalisé:

isThreatenedBy :: Colour -> State -> Position -> Bool 

Nous pouvons bien sûr écrire qu'en tant que tel:

isThreatenedBy :: Colour -> (State -> (Position -> Bool)) 

Maintenant, il devrait être clair pourquoi cette fonction ne peut être composé avec not , qui est lui-même Bool -> Bool:

(.) :: (b -> c) -> (a -> b) -> a -> c 

maintenant subsitutin g:

:: not . isThreatenedBy 

-- from `not`: 
b ~ Bool 
c ~ Bool 

-- from `isThreatenedBy: 
a ~ Colour 
b ~ (State -> (Position -> Bool)) 

Clairement b s ne correspondent pas ici.


maintenant ce que vous pouvez faire est soit pousser la composition en dehors de la première application (ce dvaergiller a fait dans sa réponse), ou introduire étape supplémentaire:

all . map not . map (isThreatenedBy color state) $ [95,96,97] 

Cela pourrait contraste typique carte-reduce modèle, mais je pense personnellement que c'est un peu plus lisible.


Alternativement, une aide de:

none = and . map not 

(Ou, comme le suggère @FrerichRaabe et généreusement fourni par Auguste De Morgan):

none = not . or 

pourrait faire encore plus clairement.

+0

n'est pas' map f. map g = map (f.g) 'cela ne faciliterait-il pas les choses? – epsilonhalbe

+0

J'aime vraiment cette réponse plus que la mienne. – dvaergiller

+0

@epsilonhalbe c'est ce que mentionne déjà l'autre réponse. Je le présente comme une alternative, et franchement, j'écrirais probablement l'aide «none» moi-même. –