2013-06-09 2 views
12

내가 Control.Lens를 사용Control.Lens를 사용하여 목록의 i 번째 요소를 업데이트하는 방법은 무엇입니까?

data Outer = Outer { _list :: [ Inner ] } 
data Inner = Inner { _bool :: Bool } 

의 라인을 따라 몇 가지 데이터 유형을 가지고,이

boolValue <- gets (^. list . to (!! i) . inner) 

I처럼 (A '국가 외부'모나드 내부) i 번째 내부의 _bool에 액세스 할 수 있습니다 또한 (나의 이해에 의해) 그러나

list ^. (to (!! i)) ^. inner %= True 

처럼 뭔가이 값을 업데이트 할 수 있도록하고 싶습니다, '받는 사람'기능 만 게터가 아닌 진정한 렌을 만듭니다 s는 getter 또는 setter로 사용할 수 있습니다.

그래서 어떻게하면이 필드를 업데이트 할 수있는 렌즈로 변환 할 수 있습니까?

답변

15

당신은 *는 Getter 이외의 렌즈와 같은 일에 (!!)를 켤 수 없습니다 -하지만 이런 종류의 할 수있는 기능이있다 : ix이 일을 액세스하기위한, 인덱스에서. 실제로는 Traversal이 아니고 Lens이 아닙니다. 여기서는 인덱스가 범위를 벗어난 경우 실패 할 수 있음을 의미합니다.하지만 인덱스가 목록에 있으면 작동합니다.

또 다른 문제가 있지만 - (^.)도 값을 가져 오는 데만 사용되는 연산자입니다. 예를 들어 호환되지 않습니다. (%=)은 첫 번째 인수로 렌즈와 같은 것을 사용합니다. 그리고 : (%=)은 기존 값보다 기능을 매핑하기위한 것입니다. 설정하려는 경우 (.=)을 사용할 수 있습니다. 그래서 당신은 아마 뭔가를 원하는 :

list . ix i . inner .= True 

* 실제로이이 작업을 수행 할 수있는 기능입니다 - 그것은 upon을라고 -하지만 멋진 사악한 마술을 사용하고 당신이 적어도 그것을 사용하지 말아야합니다 이것 (그리고 아마도 실제 코드가 아님).

+0

'ix'와'element' 사이의 차이점을 명확히 해줄 수 있습니까? 나는 Gabriel의'element'를 더 간단하게 보았 기 때문에'Index' 대신'Int'를 사용했습니다. 연결된 문서에서'ix'가 허용하는 것보다 더 일반적입니다 - 엄격하게 더 일반적입니까? – ajp

+0

나는 '요소'에 대해 생각하지 않았다. 정확히 하나가 다른 것보다 일반화 된 것은 아닙니다 ...'ix'는 특정 인덱스 유형 (예 :'Int','Map's with 색인 유형, 도메인과 함게 기능). 'element'는'Traversable' 타입을 취하고 왼쪽에서 오른쪽으로'Int' 인덱스를 셉니다. 이 경우 그들은 코니 시드에서 일어난다. – shachaf

+0

필자는 그것을 테스트하지는 않았지만'ix'가이 특별한 경우에 좀 더 효율적이라고 생각합니다 (주로'Indexing'이 좋은 코드를 생성 할 수있는 방법을 찾지 못해서 ... :-(다른 누군가는 시험에 오신 것을 환영합니다.) 또한 다소 특별 수업입니다. – shachaf

8

지정된리스트의 요소에 Traversal이다 사용 element :

list . element i . inner %= True :: Outer -> Outer 

당신이 목록 요소가되지 않을 수도 있기 때문에 그래서 Maybe를 사용하여 수행해야합니다 목록 요소 얻고 싶은 경우에 :

myList :: Outer 

myList ^? list . element i . inner :: Maybe Bool 
+0

'% ='는 상태를 수정하기위한'State ::'액션을 제공합니다. 즉,'... :: State Outer()'입니다. (또한, 질문은'. ='여기를 의미한다고 가정합니다.) – shachaf

+0

그래, 나는'% ~'을 의미하지만, 당신의 대답은 어쨌든 더 좋다고 생각합니다. –

관련 문제