Sto imparando un po 'di Haskell e ho qualche problema con queste Monade, ne ho capito e so di cosa si tratta, ma in questo caso particolare ho alcuni problemi. Mentre l'apprendimento su Lyah mi sono imbattuto in un esercitazioni che era sul calcolo delle posizioni si potrebbe ottenere a in 3 movimenti con un cavaliere (dal gioco degli scacchi), abbiamo usato la lista monade, come questo:Haskell: Monade di monade
Supponendo,
type KnightPos = (Int,Int)
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')
Questo funziona e se do la mia posizione a questa funzione, calcolerò con successo le possibili posizioni future ma ora sto cercando di implementare la monade di Writer in modo da poter recuperare come sono arrivato a questo punto. Così ho fatto questa funzione,
Supponendo,
type KnightRoute = Writer [KnightPos] KnightPos
moveKnight' :: KnightPos -> [KnightRoute]
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 $ toKr (c',r') (c,r)
where toKr pos oldpos = Writer (pos,[oldpos])
Funziona se Ho dato un KnightPos
ma utilizzando monadi non posso estrarre un KnightPos
da un KnightRoute
per eseguire la funzione un'altra volta ...
*Main> let a = moveKnight' (2,4) !! 0
*Main> runWriter a
((4,3),[(2,4)])
*Main> a >>= moveKnight'
<interactive>:4:7:
Couldn't match type ‘[]’ with ‘Writer [KnightPos]’
Expected type: KnightPos -> Writer [KnightPos] KnightRoute
Actual type: KnightPos -> [KnightRoute]
In the second argument of ‘(>>=)’, namely ‘moveKnight'’
In the expression: a >>= moveKnight'
capisco perché non funziona, ho estratto il (4,3)
dal mio scrittore, ma poi io do questo a KnightPos'
. Ma KnightPos'
restituisce un elenco di KnightRoute
dove ho bisogno di un KnightRoute
, questo è un errore di logica ma non so come fare. C'è un modo semplice per farlo con Monads?
Grazie di anticipo :)
noti che usare ' Writer' o 'WriterT' con liste come log-monoid è piuttosto inefficiente (tempo quadratico), perché continuate ad accodare a destra. Le liste delle differenze o più contenitori specializzati sono una scommessa migliore. – leftaroundabout
L'ho saputo di recente, in effetti sembra più efficiente usare l'elenco delle differenze.In ogni caso dovremmo usare Difference Lists come log-monoid ogni volta dato che non è nient'altro che più veloce? –