hier ist das Snippet zu berechnen, ob Ritter in der gewünschten Position innerhalb x bewegt bewegen kann:Haskell hinzufügen Schriftsteller Funktion
import Control.Monad (guard)
import Control.Monad.Writer
type KnightPos = (Int,Int)
-- function returning array of all possible kinght moves from desired position
moveKnight :: KnightPos -> [KnightPos]
moveKnight (c,r) = do
(c',r') <- [ (c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)
,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)
]
guard (c' `elem` [1..8] && r' `elem` [1..8])
return (c',r')
-- nice little function tells us
-- whether knight can move to desired position within x moves
reaches :: KnightPos -> KnightPos -> Int -> Bool
reaches _ _ 0 = False
reaches from pos n =
any (\p -> p == pos || reaches p pos (n-1)) $ moveKnight from
-- the result is True or False
-- does knight can move from cell 6,2 to cell 6,3 within 3 moves
main = print $ reachesm (6,2) (6,1) 3
Jetzt will ich Writer Monade in der ‚erreicht‘ funsction, aber völlig verloren hier ich komme zu etwas wie,
-- not so nice and little yet
reachesm :: KnightPos -> KnightPos -> Int -> Writer [String] [Bool]
reachesm _ _ 0 = return [False]
reachesm from pos n = do
tell [ "-->" ++ (show pos) ]
p <- moveKnight from -- ???
np <- reachesm p pos (n-1)
return(p == pos || any np)
aber es kompiliert nicht sogar. Ich vermute, es ist Zeit für Monad-Transformers hier?
UPD: So, endlich kamen wir zu folgenden Rewrite, aber ich damit noch nicht zufrieden, beacuse reachesm anders aus reinen Variante läuft, es recurses alle n Schritte tief, aber ich erwarten, dass es zu stoppen Iteration, sobald es die Antwort gefunden hat. Ist es schwierig, das so zu ändern? Und eine andere Frage ist über Faulheit, es scheint, dass in tun Block Berechnungen sind nicht faul ist es wahr?
reachesm :: KnightPos -> KnightPos -> Int -> Writer [String] Bool
reachesm _ _ 0 = return False
reachesm from pos n = do
tell [ "-->" ++ (show from) ]
let moves = moveKnight from
np <- forM moves (\p -> reachesm p pos (n-1))
return (any (pos ==) moves || or np)
Laziness hängt von der Monade - da Sie vom Konzept her sind für alle Pfade zu fragen, und da das Ergebnis des Schriftstellers konzeptionell alle Pfade enthält, dann können Sie nicht bekommen das volle Ergebnis des Schreibers unter Beibehaltung ausreichender Faulheit. Du brauchst auch frühes Beenden - und du kannst das bekommen, indem du einen weiteren Transformator zum Stack hinzufügst - schau dir die Exception-Monade an, die in deinem Fall wirklich die Exit-Monade sein sollte: http://www.haskell.org/haskellwiki/New_monads/MonadExit – sclv