실제로 모든 모듈로 자동으로 가져 오는 표준 라이브러리 인 Prelude 에서 정의되는 일반적인 데이터 생성자입니다 .
아마도 구조적으로
정의는 다음과 같습니다.
data Maybe a = Just a
| Nothing
이 선언은 유형 Maybe a
변수에 의해 매개 변수화되는 유형을 정의합니다. 즉 a
, 대신 모든 유형과 함께 사용할 수 있습니다 a
.
구성 및 파괴
형식에는 두 개의 생성자 Just a
와 Nothing
. 형식에 여러 생성자가있는 경우 가능한 생성자 중 하나만 사용하여 형식 값이 생성되어야합니다. 이러한 유형의 값 중 하나를 통해 제조 하였다 Just
또는 Nothing
다른 (비 에러) 가능성은 없다.
Nothing
매개 변수 유형이 없기 때문에 생성자로 사용될 때 Maybe a
모든 유형 의 유형 멤버 인 상수 값의 이름을 지정합니다 a
. 그러나 Just
생성자에는 유형 매개 변수가 있습니다. 즉, 생성자로 사용될 때 유형에서으로의 함수처럼 작동 a
합니다 Maybe a
. 즉, 유형이a -> Maybe a
따라서 유형의 생성자는 해당 유형의 값을 빌드합니다. 다른 측면은 그 값을 사용하고 싶을 때이며 패턴 매칭이 작동하는 곳입니다. 함수와 달리 생성자는 패턴 바인딩 표현식에서 사용할 수 있으며, 이는 둘 이상의 생성자가있는 유형에 속하는 값의 케이스 분석 을 수행 할 수있는 방법입니다 .
Maybe a
패턴 일치에서 값 을 사용하려면 다음 과 같이 각 생성자에 대한 패턴을 제공해야합니다.
case maybeVal of
Nothing -> "There is nothing!"
Just val -> "There is a value, and it is " ++ (show val)
이 경우 식에서 첫 번째 패턴은 값이 Nothing
이면 일치하고 두 번째 패턴은 값이로 생성 된 경우 일치합니다 Just
. 두 번째 항목 이 일치하면 일치하는 값이 생성 될 때 생성자 val
에 전달 된 매개 변수에 이름 을 바인딩합니다 Just
.
의미하는 것
아마도 이것이 어떻게 작동하는지 이미 잘 알고 계실 것입니다. Maybe
값에 대한 마법은 없습니다. 그냥 일반적인 Haskell Algebraic Data Type (ADT) 일뿐입니다. 그러나 Integer
예에서 와 같이 유형 Nothing
을 가치 부족을 나타내는 추가 값 ( )이 있는 새로운 컨텍스트로 효과적으로 "리프트"하거나 확장하기 때문에 상당히 많이 사용됩니다 ! 유형의 시스템은 당신이 얻을 수 있도록하기 전에 당신이 여분의 값을 확인해야 Integer
하는 수도 가. 이것은 엄청난 수의 버그를 방지합니다.
오늘날 많은 언어가 NULL 참조를 통해 이러한 종류의 "값이없는"값을 처리합니다. 저명한 컴퓨터 과학자 인 Tony Hoare (그는 Quicksort를 발명했고 Turing Award 수상자)는 그의 "10 억 달러의 실수" 로이를 소유하고 있습니다 . Maybe 유형은이 문제를 해결할 수있는 유일한 방법은 아니지만 효과적인 방법으로 입증되었습니다.
아마도 Functor로서
이러한 기존의 유형에 대한 작업을 할 수있는 다른 하나 개의 유형을 변환의 개념 또한 새로운 유형의 작업으로 변환 할 수라는 하스켈 타입 클래스 뒤에 개념 Functor
, Maybe a
유용한 경우가 있습니다.
Functor
는 fmap
기본 유형 (예 Integer
:)의 값에 걸쳐있는 함수를 해제 된 유형 (예 :)의 값에 걸쳐있는 함수에 매핑 하는라는 메서드를 제공합니다 Maybe Integer
. 값 fmap
에 대해 작동하도록 변환 된 함수 Maybe
는 다음과 같이 작동합니다.
case maybeVal of
Nothing -> Nothing -- there is nothing, so just return Nothing
Just val -> Just (f val) -- there is a value, so apply the function to it
따라서 Maybe Integer
값 m_x
과 Int -> Int
함수 가있는 경우 실제로 값이 있는지 여부 에 대한 걱정없이에 직접 함수를 적용 f
할 수 있습니다 . 실제로 해제 된 함수 의 전체 체인 을 값에 적용 할 수 있으며 완료했을 때 한 번만 명시 적으로 확인하는 것에 대해 걱정할 필요가 있습니다.fmap f m_x
f
Maybe Integer
Integer -> Integer
Maybe Integer
Nothing
아마도 모나드로서
당신이 a의 개념에 얼마나 익숙한 지 잘 모르겠지만 Monad
, 적어도 IO a
전에 사용 해본 적이 있고 타입 시그니처 IO a
는 Maybe a
. 비록 IO
그것이 당신에게 그것의 생성자를 노출하지 않습니다 따라서 만 하스켈 런타임 시스템에 의해 "실행"할 수 있다는 점에서 특별하다, 그것은 또한 아직 Functor
인뿐만 아니라 Monad
. 사실, a Monad
가 Functor
몇 가지 추가 기능이 있는 특별한 종류 라는 중요한 의미가 있지만 여기에 들어가는 것은 아닙니다.
어쨌든, 모나드 IO
는 "값을 초래하는 계산"을 나타내는 새로운 유형에 대한 맵 유형을 좋아 하고 , 정규 함수를 "평가를 통해 얻은 값을 생성하는 계산으로 바꾸는 Monad
매우 fmap
유사한 함수 를 통해 함수를 유형 으로 리프트 할 수 있습니다 liftM
." 함수."
아마도 (지금까지 읽으 셨다면) Maybe
그것도 Monad
. "값을 반환하지 못할 수있는 계산"을 나타냅니다. fmap
예제 와 마찬가지로 이를 통해 각 단계 후에 명시 적으로 오류를 확인하지 않고도 전체적인 계산을 수행 할 수 있습니다. 실제로 Monad
인스턴스가 생성 되는 방식은 Maybe
값에 대한 계산이 a 가 발생 하자마자 중지Nothing
되므로 계산 도중에 즉시 중단되거나 값이없는 반환과 같습니다.
당신은 아마 쓸 수 있었을 것입니다
앞서 말했듯 Maybe
이 언어 구문이나 런타임 시스템에 구워진 유형 에는 고유 한 것이 없습니다 . Haskell이 기본적으로 제공하지 않았다면 모든 기능을 직접 제공 할 수 있습니다! 사실, 어쨌든 다른 이름으로 직접 다시 작성하고 동일한 기능을 얻을 수 있습니다.
Maybe
이제 유형과 생성자 를 이해 하셨기를 바랍니다 .하지만 여전히 불분명 한 것이 있으면 알려주세요!
Maybe
다른 언어가 사용 하는 곳에서null
또는nil
(NullPointerException
모든 구석에 숨어있는 끔찍한)을 사용 한다는 점을 언급해야합니다 . 이제 다른 언어도이 구조를 사용하기 시작합니다. Scala asOption
, 심지어 Java 8도Optional
유형 을 갖습니다 .