2016-03-31 12 views
1

我目前正在Haskell中進行棋盤遊戲。這裏是我的功能,評估爲True,當你餵給它的正確的參數鑄造在kingsside。 (問題部分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 ::顏色 - >遊戲狀態 - >內部 - >布爾

當我撰寫不和isThreatenedBy我應該得到 一個功能型的f = (not . isThreatenedBy)

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

但真正讓我像我想的Colour -> Bool。 然後我部分地與顏色和遊戲狀態 的值適用它並且將所得的函數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

'Data.Tuple'中'swap'的名稱也被「取」爲'swap ::(a,b) - >(b,a)'。 – 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] 

這可能比較典型的map-reduce模式,但我個人認爲它更具可讀性。


或者,一個幫手:

none = and . map not 

(或者,如@FrerichRaabe建議和奧古斯都德·摩根慷慨地提供):

none = not . or 

能做出這樣更加清晰。

+0

不是'map f。 map g = map(f。g)'會不會讓事情變得更簡單? – epsilonhalbe

+0

我其實比我的更喜歡這個答案。 – dvaergiller

+0

@epsilonhalbe這是其他答案已經提到的內容。我把它作爲一個替代方案,坦率地說,我可能會自己寫'none'助手。 –

相關問題