Trong hàm test
, tôi duyệt qua danh sách, tạo thấu kính từ các thành viên của nó rồi in một số dữ liệu. Điều này làm việc khi tôi sử dụng một kiểu gọi quan trọng. Nó không đánh máy khi tôi làm cho nó điểm-miễn phí.Tạo ống kính không điểm không nhập kiểm tra
Tại sao lại xảy ra trường hợp này và làm cách nào tôi có thể giải quyết vấn đề này? Có vẻ như với tôi rằng GHC không giữ lại thông tin rằng xếp hạng cao hơn f
(trong ống kính) là Functor
khi sử dụng kiểu không có điểm, nhưng tôi không quá chắc chắn.
Tôi đang sử dụng 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.
Tôi không biết chi tiết, nhưng tôi chắc chắn nó có liên quan đến các loại xếp hạng cao hơn gây ra một số vấn đề về nhập. Việc truyền các đối số 'Lens' có thể gây ra vấn đề đó. Nó có thể sẽ hoạt động nếu bạn sử dụng 'ALens' thay vì' Lens', vì nó được thiết kế để truyền xung quanh. –
@DavidYoung Bạn * có thể * làm điều đó với 'ALens', nhưng sau đó hàm được gọi phải rõ ràng' cloneLens' nó trở lại một ống kính bình thường trước khi sử dụng nó. Đó là bình thường chỉ thích hợp cho một chức năng mà thực sự cần các tính năng ống kính đầy đủ của đối số của nó. –
@DavidYoung: Tôi sẽ phải xem xét nó. Một google nhanh chóng không đưa ra bất kỳ hướng dẫn/ví dụ cho 'ALens' trên' Lens', nhưng tôi sẽ có thể tìm ra nó. Thời gian để gọi ngày nghỉ ngay bây giờ. –