IO [[Char]]
과 IO()
을 바인딩해도 괜찮지 만 Maybe
을 IO
으로 바인딩 할 수는 없습니다. 누군가이 완화 작용이 나쁜 디자인으로 이어질 수있는 예를 들어 줄 수 있습니까? Monad의 다형성 유형에서 자유가 허용되는 이유는 무엇입니까?같은 모나드 타입 만이`>> '연산자로 연결되는 것을 허용하는 논리는 무엇입니까?
답변
많은 이론적 인 이유가 있습니다. "그게 뭔지는 Monad
이 아닙니다." 그러나 잠시 그 단계에서 벗어나 구현 세부 사항을 살펴 보겠습니다.
먼저 꺼짐 - Monad
은 마법이 아닙니다. 그것은 단지 표준 타입 클래스입니다. Monad
의 인스턴스는 누군가가 하나를 작성할 때만 생성됩니다.
해당 인스턴스를 작성하는 것은 (>>)
의 작동 방식을 정의합니다. 일반적으로 (>>=)
이라는 용어로 암시 적으로 기본 정의를 통해 수행되지만, 이는 단지 (>>=)
이 더 일반적인 연산자라는 증거이며, 쓰기는 (>>)
과 동일한 결정을 내릴 것을 요구합니다.
더 일반적인 유형의 다른 연산자를 사용하는 경우 두 가지 질문에 답해야합니다. 첫째, 유형은 무엇입니까? 둘째, 구현을 제공하는 방법에 대해 어떻게 생각하십니까? 질문에서 원하는 유형이 무엇인지 분명하지 않습니다. 다음 중 하나 일 것입니다 :
class Poly1 m n where
(>>) :: m a -> n b -> m b
class Poly2 m n where
(>>) :: m a -> n b -> n b
class Poly3 m n o | m n -> o where
(>>) :: m a -> n b -> o b
이 모두를 구현할 수 있습니다. 그러나 실제적으로 사용하기 위해서는 두 가지 중요한 요소를 잃게됩니다.
- 함께 사용하려는 모든 유형 쌍에 대한 인스턴스를 작성해야합니다. 이것은 각 유형에 대한 인스턴스보다 훨씬 복잡한 작업입니다. 뭔가 약
n
대n^2
. - 예측 가능성이 떨어집니다. 수술은 무엇입니까 도합니까? 이론과 실습이 교차하는 곳입니다.
Monad
의 이론은 작업에 많은 제한을 가하고 있습니다. 이러한 제한을 "모나드 법"이라고합니다. 그것들은 Haskell에서 검증 할 수있는 능력을 넘어서는 것이지만, 그것들을 따르지 않는 어떤Monad
인스턴스는 버그가있는 것으로 간주됩니다. 최종 결과는Monad
작업이 수행하는 작업과 수행하지 않는 작업에 대한 직관을 신속하게 구축 할 수 있다는 것입니다. 관련된 모든 유형의 세부 사항을 조회하지 않고도 사용할 수 있습니다. 특성에 대한 지식을 알고 있기 때문입니다. 제가 제안한 가능한 클래스 중 어느 것도 당신에게 그런 종류의 보장을주지 않습니다. 당신은 그들이 무엇을하는지 전혀 모른다.
는 내가 제대로 질문을 이해 모르겠지만, 그것은 당신이 []
와 IO
을 구성 할 수 같은 의미에서 IO
또는 []
으로 Maybe
를 구성 할 확실히 가능합니다. 당신이 :t
를 사용 GHCI의 형식을 선택하면 예를 들어
는
getContents >>= return . lines
당신에게 IO [String]
을 제공합니다.당신이
>>= return . map Text.Read.readMaybe
를 추가 할 경우 당신은
IO
,
[]
및
Maybe
의 구성입니다
IO [Maybe a]
의 유형을 얻을.
>>= return . Data.Maybe.catMaybes
으로 전달하여 IO [a]
으로 플랫화 할 수 있습니다. 그런 다음 구문 분석 된 유효한 입력 행의 목록을 다시 평평하게하고 출력을 계산하는 함수에 전달할 수 있습니다.
입력하여 프로그램을 함께
import Text.Read (readMaybe)
import Data.Maybe (catMaybes)
main :: IO()
main = getContents >>= -- IO String
return . lines >>= -- IO [String]
return . map readMaybe >>= -- IO [Maybe Int]
return . catMaybes >>= -- IO [Int]
return . (sum :: [Int] -> Int) >>= -- IO Int
print -- IO()
를 이러는 :
1
2
Ignore this!
3
인쇄 6
.
또한 IO (Maybe [String])
작업 할 수있을 것이다하는 Maybe [IO String]
등
당신은뿐만 아니라 >>
이 작업을 수행 할 수 있습니다. 고안된 예 : getContents >> (return . Just) False
은 입력을 읽고 무시하고 IO (Maybe Bool)
을 돌려줍니다.
typeclass 인스턴스가 실제로 지원하는 연산 만 사용할 수 있습니다. 'Monad'의 인스턴스는'(>> =) :: m a -> (a -> m b) -> m b'만을 제공합니다. 즉, 전체적으로 동일한'm'을 제한적으로 요구합니다. 임의의 "bind over anything"연산이 있다는 의미있는 의미를 알 수 있다면 꼭 모든 인스턴스를 typeclass로 지정하고 알고있는만큼의 인스턴스를 생성 할 수 있습니다. '(>> =) :: m a -> (a -> n b) -> n b'와 같은 클래스는 소비자를 필요로하지 않지만 구현자를 위해 현명하게 만족시키는 것은 거의 불가능합니다. –
'Monad' 타입 클래스 뒤에있는 이론은'm'이 같은 펑터가되도록 요구합니다; 이 속성은 IO를 처리하기위한 기초로 적합하게 만드는 요소입니다. 다른 유형으로 전환하여'IO'에서 탈출 할 수 없습니다. – chepner
'아마도'아마도'IO'와 어떻게 묶을 수 있을까요? 'IO' 모나드는 상태를 변경시키지 않으며 * 상태를 변경하는 * 방법을 설명합니다. –