2016-03-31 3 views
1

В настоящее время я работаю над шахматной игрой в Haskell. Вот моя функция, которая оценивает значение «Истина», когда вы подаете ей правильные параметры для рокировки на короле. (проблема в части 1 & 2, посмотрите на комментарии). Я попытался использовать композицию функций, чтобы найти более сжатое решение, но для меня это не получилось. Я был бы рад, если бы кто-то мог бы взглянуть на то, что я сделал, и объяснить, где я пошло не так ... большое спасибо заранееЧастичное применение Функции и их составление впоследствии

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 

вот typesignatures для используемых функций

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

я хотел переписать очень многословные части 1 и 2, как:

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

, но я не могу обойти ErrorMessage из:

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 :: Цвет -> GameState -> Int -> Bool

когда я сочинить не и isThreatenedBy я должен получить функция f = (not . isThreatenedBy) типа

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

но на самом деле я получаю что-то вроде Colour -> Bool. Тогда я частично применить его со значениями цвета и GameState и результирующая функция F»должна быть типа

f' :: Int -> Bool

, а затем я своего рода карту его над списком [95,96,97] и увидеть если каждый элемент удовлетворяет f' через all

или так был план ...

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 

его странно, что (нет. wasMoved) применяется слишком много аргументов в Error1 и, вероятно, слишком мало ошибок 2, но я не могу перемещать элементы списка внутри скобок, в противном случае я мог бы просто вернуться к той точке, с этого я начал

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

же, как и выше ошибки 1 (только на этот раз с 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. 

, как по ошибке 2 я думаю

+0

Обратите внимание, что то, что вы называете 'swap', уже предусмотрено как функция' flip'. – Bakuriu

+0

Название 'swap' также« взято »для' swap :: (a, b) -> (b, a) 'в' Data.Tuple'. – dfeuer

+0

спасибо вам обоим, я не знал, что ... но я буду помнить об этом – Fynn

ответ

3

я мог бы неправильно это одному немного, но посмотрите на это. Это НЕ работает:

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 

Это не тип проверки. Причиной этого является тот факт, что функция (.) выполняет две функции в качестве параметров, причем эти две функции принимают по одному параметру каждый. В этом примере функция (+) принимает два параметра и, следовательно, имеет неправильный тип.Это работает:

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

Потому что я превратил функцию в функцию, которая принимает только один параметр. Ваша isThreatenedBy функция может быть изменена таким же образом:

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

Не уверен, что если бы это было на самом деле вы корень проблемы, но попробовать его.

+0

Обратите внимание, что 'f. g' эквивалентно '\ x -> f (g x)'. Вы * можете * (но ** не должны **) использовать '(.). (.) $ f g', чтобы получить эквивалент '\ x y -> f (g x y)' или даже '((.). (.)). (.) $ f g', чтобы получить '\ x y z -> f (g x y z)'. Поэтому используйте '((.). (.)). (.) $ Not isThreatenedBy' должен работать и что было предназначено ... хотя избегайте этого обмана. – Bakuriu

+0

он отлично работает, и теперь я понимаю, что я сделал неправильно Я даже не частично применял 'isThreatendBy' правильно , потому что я положил его в скобки, которые вырезали приложение ... – Fynn

3

Давайте начнем с пользовательским предикатом:

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

Конечно, мы можем написать, что как таковые:

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

Теперь, должно быть ясно, почему эта функция не может быть составлена ​​с not , которая сама по себе является Bool -> Bool:

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

Теперь subsitutin g:

:: not . isThreatenedBy 

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

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

Ясно b s здесь не совпадают.


Теперь то, что вы можете сделать, это либо нажать композицию за пределами первой заявки (что dvaergiller сделал в своем ответе), или ввести дополнительный шаг:

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

Это может контрастировать типичная карта-свертка но я лично считаю, что это немного читаемо.


В качестве альтернативы, помощник:

none = and . map not 

(Или, как это было предложено @FrerichRaabe и щедро предоставленной Augustus De Morgan):

none = not . or 

могли бы сделать это еще яснее.

+0

не является' map f. map g = map (f. g) 'не облегчит это? – epsilonhalbe

+0

Мне действительно нравится этот ответ больше, чем мой. – dvaergiller

+0

@epsilonhalbe вот что говорит другой ответ. Я представляю его в качестве альтернативы, и, честно говоря, я бы, вероятно, сам написал «нет». –

Смежные вопросы