2015-01-08 16 views
6

Tôi đang gặp khó khăn với lenszippers. Xem xét bên dưới đang chạy trong ghcibước vào dây kéo với ống kính `to`

> import Control.Lens 
> import Control.Zipper 
> 
> :t within (ix 1) $ zipper ([1,2,3] :: [Int]) 
> within (ix 1) $ zipper ([1,2,3] :: [Int]) 
    :: Control.Monad.MonadPlus m => m (Zipper Top Int [Int] :>> Int) 

data A t = A t, làm thế nào tôi có thể tạo ra loại dây kéo như: Control.Monad.MonadPlus m => m (Zipper Top Int [Int] :>> A Int)?

tôi đã cố gắng within (ix 1 . to A) $ zipper ([1,2,3] :: [Int]) nhưng nó mang lại một lỗi:

Could not deduce (Contravariant 
        (Bazaar (Indexed Int) (A Int) (A Int))) 
    arising from a use of ‘to’ 
from the context (Control.Monad.MonadPlus m) 
    bound by the inferred type of 
      it :: Control.Monad.MonadPlus m => 
       m (Zipper Top Int [Int] :>> A Int) 
    at Top level 
In the second argument of ‘(.)’, namely ‘to A’ 
In the first argument of ‘within’, namely ‘(ix 1 . to A)’ 
In the expression: within (ix 1 . to A) 

Trả lời

2

Một cách là làm cho một Iso và soạn với điều đó. Trong ghci:

> import Control.Lens 
> import Control.Zipper 
> 
> data A t = A t 
> let _A = iso A (\(A a) -> a) 
> 
> let a = within (ix 1 . _A) $ zipper ([1,2,3] :: [Int]) 
> :t a 
a :: MonadPlus m => m (Zipper Top Int [Int] :>> A Int) 
> a ^? _Just . focus 
Just (A 2) 

Chỉnh sửa: Lý do bạn cần (\(A a) -> a) là để bạn có thể thoát ra.

> data A t = A t 
> let _A = iso A (error "Can't unA") 
> 
> let a = within (ix 1 . _A) $ zipper ([1,2,3] :: [Int]) 
> a ^? _Just . focus 
Just (A 2) 
> fmap upward a ^? _Just . focus 
Just [1,*** Exception: Can't unA 

Tôi không nghĩ rằng có cách hợp lệ để thực hiện việc này mà không có chức năng trích xuất A. Bạn có thể viết một hợp lệ Traversal nhưng nó vẫn sẽ không hoạt động đúng:

> data A t = A t 
> let _A f a = a <$ f (A a) 
> 
> let a = within (ix 1 . _A) $ zipper ([1,2,3] :: [Int]) 
> let b = a & _Just . focus .~ A 10 
> b ^? _Just . focus 
Just (A 10) 
> fmap upward b ^? _Just . focus 
Just [1,2,3] -- Should be Just [1, 10, 3] 
+0

Có cách nào để làm điều đó mà không specyfing '(\ (A a) -> a)' chức năng? Tôi có thể vượt qua đây 'undefined' nếu trong trường hợp của tôi nó không phải là hiển nhiên? – remdezx

+0

Không thực sự. Vấn đề là bạn sẽ không thể quay trở lại. Sử dụng 'upward' để thoát ra sẽ cho' undefined'. – cchalmers

+1

Tôi hiểu ... Có lựa chọn nào khác ngoài 'Iso' không? – remdezx

Các vấn đề liên quan