Nella funzione test
, ho attraversato un elenco, generato obiettivi dai suoi membri e quindi stampato alcuni dati. Funziona quando uso uno stile di chiamata puntuale. Non riesce a tipografare quando lo faccio senza punti.La creazione di obiettivi senza punto non digita il controllo
Perché è questo il caso e come posso risolvere questo problema?
Sembra a me che GHC non sta mantenendo le informazioni che più alto-classificato f
(nella lente) è un Functor
quando si utilizza stile libero-punto, ma io non sono troppo sicuro.
sto usando GHC 7.8.3
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad
import Data.List
import Data.Maybe
type PlayerHandle = String
data Player = Player { _playerHandle :: PlayerHandle }
makeLenses ''Player
data GameState = GameState { _gamePlayers :: [Player] }
makeLenses ''GameState
type PlayerLens = Lens' GameState Player
getPlayerLens :: PlayerHandle -> PlayerLens
getPlayerLens handle f st = fmap put' get'
where
players = st^.gamePlayers
put' player = let
g p = case p^.playerHandle == handle of
True -> player
False -> p
in set gamePlayers (map g players) st
get' = f $ fromJust $ find (\p -> p^.playerHandle == handle) players
printHandle :: GameState -> PlayerLens -> IO()
printHandle st playerLens = do
let player = st^.playerLens
print $ player^.playerHandle
test :: GameState -> IO()
test st = do
let handles = toListOf (gamePlayers.traversed.playerHandle) st
--
-- Works: Pointful
--forM_ handles $ \handle -> printHandle st $ getPlayerLens handle
--
-- Does not work: Point-free
forM_ handles $ printHandle st . getPlayerLens
main :: IO()
main = test $ GameState [Player "Bob", Player "Joe"]
Test.hs:45:38:
Couldn't match type `(Player -> f0 Player)
-> GameState -> f0 GameState'
with `forall (f :: * -> *).
Functor f =>
(Player -> f Player) -> GameState -> f GameState'
Expected type: PlayerHandle -> PlayerLens
Actual type: PlayerHandle
-> (Player -> f0 Player) -> GameState -> f0 GameState
In the second argument of `(.)', namely `getPlayerLens'
In the second argument of `($)', namely
`printHandle st . getPlayerLens'
Failed, modules loaded: none.
Non conosco i dettagli, ma sono abbastanza sicuro che abbia qualcosa a che fare con tipi ordinati superiori causando alcuni problemi di battitura. Passare argomenti 'Lens' può causare questo tipo di problema. Probabilmente funzionerà se usi 'ALens' invece di' Lens', dal momento che è progettato per essere passato in giro. –
@DavidYoung Si * può * farlo con 'ALens', ma poi la funzione chiamata deve esplicitamente' cloneLens' su un obiettivo normale prima di usarlo. Normalmente ciò è appropriato solo per una funzione che ha veramente bisogno delle caratteristiche lente dell'argomento. –
@DavidYoung: dovrò esaminarlo. Un rapido google non ha dato adito a tutorial/esempi per 'ALens' su' Lens', ma dovrei essere in grado di capirlo. È ora di chiamare il giorno in cui si chiude. –