이 질문은 이전 질문에 대한 후속 질문입니다. State 및 IO Monads
내 목표는 파일에 대한 간단한 텍스트 편집기를 만드는 것입니다. Editor
기본 데이터 구조에 대한 모든 편집 작업을 멋지게 캡슐화 하는 구성 요소가 이미 있습니다 .
이전 질문에 대한 답변 덕분에 프로그램을 리팩터링하여 이제 멋진 모나드 변환기 스택을 얻을 수있었습니다.
type Session = StateT AppState (StateT Editor IO)
AppState
응용 프로그램의 전역 상태 (현재 열린 파일 등) Editor
를 보유하고 앱 편집 구성 요소의 내부 상태 (캐럿이있는 위치 등)를 나타냅니다. 응용 프로그램의 주요 동인 기능이 있습니다.
eventLoop :: Session ()
지금까지는 훌륭했지만, main
함수 에서 트랜스포머 스택을 실제로 시작하는 방법을 모르겠습니다 . Main은 IO
내 스택의 맨 밑에 있는 모나드 에서 무언가를 반환해야합니다 . 내 생각 엔 초기화 AppState
하고 다음과 같은 작업을 수행해야합니다.
main = do
let initialAppState = ...
return $ runStateT eventLoop initialAppState
하지만 Editor
지금 어디에서 초기화 합니까?
저를 혼란스럽게하는 가장 중요한 점은 리팩토링 전에 Editor
단순히 다음의 멤버였습니다 AppState
.
data AppState = { editor :: Editor , ... }
그러나 이제는 AppState
트랜스포머 스택에서 벗어나 약간의 형제가되었습니다. 수정하는 것은 전체 상태를 수정하는 것을 의미하기 때문에 Editor
여전히 일부가 되어서는 안 AppState
됩니까?
어떻게 제대로 내를 초기화 할 Session
모두 AppState
와 Editor
다음 내에서 실행 main
?
주 기능에서 트랜스포머 스택을 실제로 시작하는 방법은 무엇입니까?
main =
flip evalStateT initialAppState $
flip evalStateT initialEditorState $
eventLoop
where
initialAppState =
error "Define me"
initialEditorState =
error "Define me"
수정하는 것은 전체 상태를 수정하는 것을 의미하기 때문에 에디터는 여전히 AppState의 일부 여야하지 않습니까?
때에 따라 다르지.
Monad Transformer의 목적은 애드혹 방식으로 기능을 확장하는 것임을 기억하십니까? 즉, 기존 코드베이스를 다시 작성하지 않고 추가하는 것입니다. 따라서 Editor 및 AppState의 격리 된 API가 이미있는 경우 변환기 스택을 사용하여 다른 "돔"모듈에 결합하는 것이 더 쉽습니다.
OTOH는 초기 아키텍처 관점에서 볼 때 AppState가 무엇보다도 Editor (EditorState라고 부릅니다)를 포함하는 데이터 구조라는 것이 전적으로 합리적입니다. 이러한 경우 AppState의 API는 Editor의 API를 캡슐화해야합니다. "렌즈"라이브러리는 이러한 복합 데이터 구조로 작업하는 데 많은 도움이 될 것입니다 (비록 학습 곡선이 가파르다는 것을 언급해야합니다).
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다