먼저 추상적 개념 학습과 구체적인 개념 학습을 구별 해 봅시다 .
당신은 그들이 완전히 유비쿼터스라는 단순한 이유 때문에 모든 특정 예제를 무시하지 않을 것입니다. 실제로 추상화 는 특정 예제를 사용하여 수행 할 작업을 통합 하기 때문에 대부분 존재합니다 .
반면 추상화 자체는 확실히 유용 하지만 즉시 필요한 것은 아닙니다. 추상화를 완전히 무시하고 다양한 유형을 직접 사용하여 얻을 수 있습니다. 당신은 그것들을 결국 이해하고 싶을 것이지만, 나중에 다시 돌아올 수 있습니다. 사실, 당신이 그렇게한다면, 당신이 그것으로 돌아 왔을 때 이마를 때리고 왜 당신이 편리한 범용 도구를 사용하는 대신 왜 힘든 일을했는지 궁금해 할 것입니다.
가지고 Maybe a예를 들어. 데이터 유형일뿐입니다.
data Maybe a = Just a | Nothing
자체 문서화를 제외한 모든 것입니다. 선택적 값입니다. 유형이 "그냥" a있거나 아무 것도 없습니다. 존재하지 않을 수 Maybe String있는 String값을 찾기 위해 반환 하는 일종의 조회 기능이 있다고 가정 해보십시오 . 따라서 값에 패턴 일치를 지정하여 값이 무엇인지 확인하십시오.
case lookupFunc key of
Just val -> ...
Nothing -> ...
그게 다야!
실제로 필요한 것은 없습니다. Functors 또는 Monads 또는 다른 것 없음 . 그것들은 Maybe a값 을 사용하는 일반적인 방법을 표현 하지만 ... "디자인 패턴"이라는 관용구입니다.
당신이 정말로 그것을 완전히 피할 수없는 곳은입니다 IO. 그러나 그것은 어쨌든 신비한 블랙 박스이므로 그것이 무엇인지 Monad또는 무엇을 의미하는지 이해하려고 노력할 가치가 없습니다 .
사실, 여기 당신 이IO 지금 정말로 알아야 할 모든 것에 대한 치트 시트 가 있습니다 :
무언가가 type IO a인 경우 이는 무언가를 수행 하고 a가치를 내뿜는 절차 임을 의미합니다 .
do표기법을 사용하여 코드 블록 이 있으면 다음과 같이 작성하십시오.
do -- ...
inp <- getLine
-- etc...
... 의 오른쪽 에서 프로 시저 를 실행하고<- 결과를 왼쪽의 이름에 지정합니다.
이와 같은 것이 있다면 :
do -- ...
let x = [foo, bar]
-- etc...
...의 오른쪽에 일반 표현식 (프로 시저가 아님)의 값을 =왼쪽의 이름에 할당하는 것을 의미합니다 .
다음과 같이 값을 할당하지 않고 무언가를 넣는 경우 :
do putStrLn "blah blah, fishcakes"
... 프로 시저를 실행하고 반환하는 것은 무시한다는 의미입니다. 일부 절차는 유형이 IO ()고마웠다 ()만이 절차를 의미한다 무언가를하고 값을 반환하지 않습니다 그래서, 유형 분류 아무 말도하지 않는 자리의입니다. void다른 언어 의 함수 와 비슷합니다 .
동일한 절차를 두 번 이상 실행하면 다른 결과를 얻을 수 있습니다. 그것은 일종의 아이디어입니다. 이것이 IO값에서 "제거"하는 방법 IO이없는 이유입니다. 어떤 것이 값이 아니기 때문에 값을 얻는 절차입니다.
do블록 의 마지막 행은 할당이없는 일반 프로 시저 여야합니다. 여기서 해당 프로 시저의 반환 값은 전체 블록의 반환 값이됩니다. 반환 값에 이미 할당 된 일부 값을 사용하려면이 return함수는 일반 값을 사용하여 해당 값을 반환하는 비 작동 절차를 제공합니다.
그 외에는 특별한 것이 없습니다 IO. 이러한 절차는 실제로는 평범한 값이므로 다른 방법으로 전달하여 결합 할 수 있습니다. 그들이 무언가를 do함으로써 어딘가에 있는 블록 에서 실행될 때만 가능 main합니다.
따라서 완전히 지루하고 틀에 박힌 전형적인 프로그램과 같은 것에서 :
hello = do putStrLn "What's your name?"
name <- getLine
let msg = "Hi, " ++ name ++ "!"
putStrLn msg
return name
... 당신은 명령형 프로그램처럼 그것을 읽을 수 있습니다. 우리는라는 절차를 정의하고 있습니다 hello. 실행되면 먼저 이름을 묻는 메시지를 인쇄하는 절차를 실행합니다. 다음으로 입력 줄을 읽고 결과를 할당하는 프로 시저를 실행합니다 name. 그런 다음 이름에 표현식을 할당합니다 msg. 그런 다음 메시지를 인쇄합니다. 그런 다음 전체 블록의 결과로 사용자 이름을 반환합니다. 이후 nameA는 String,이 수단 hello리턴한다이다가 절차 String, 그래서이 유형이가 IO String. 이제이 절차를 실행하는 것처럼 다른 곳에서이 절차를 실행할 수 있습니다 getLine.
Pfff, 모나드 누가 필요합니까?