Programing

Haskell에서 "Just"구문은 무엇을 의미합니까?

crosscheck 2020. 8. 5. 07:50
반응형

Haskell에서 "Just"구문은 무엇을 의미합니까?


이 키워드의 기능에 대한 실제 설명을 위해 인터넷을 검색했습니다. 내가 본 모든 Haskell 튜토리얼은 무작위로 사용하기 시작하고 그것이 무엇을하는지 설명하지 않습니다 (그리고 많은 것을 보았습니다).

다음 은를 사용하는 Real World Haskell 의 기본 코드입니다 Just. 코드의 기능을 이해하지만 목적이나 기능이 무엇인지 이해하지 못합니다 Just.

lend amount balance = let reserve    = 100
                      newBalance = balance - amount
                  in if balance < reserve
                     then Nothing
                     else Just newBalance

내가 관찰 한 바에 따르면, 그것은 Maybe타이핑 과 관련이 있지만, 내가 배운 것은 거의 전부입니다.

Just의미가 무엇인지에 대한 좋은 설명은 대단히 감사하겠습니다.


실제로는 Prelude 에서 정의되는 일반적인 데이터 생성자입니다. Prelude 는 모든 모듈로 자동으로 가져 오는 표준 라이브러리입니다.

어쩌면 무엇인가, 구조적으로

정의는 다음과 같습니다.

data Maybe a = Just a
             | Nothing

이 선언은 형식 Maybe a변수에 의해 매개 변수가 지정된 형식을 정의합니다 a. 이는 형식 대신에 형식을 사용할 수 있음을 의미합니다 a.

구성 및 파괴

유형은 두 개의 생성자를 가지고 Just aNothing. 유형에 여러 생성자가있는 경우 가능한 생성자 중 하나만 사용하여 유형의 값을 구성해야합니다. 이러한 유형의 값 중 하나를 통해 제조 하였다 Just또는 Nothing다른 (비 에러) 가능성은 없다.

이후는 Nothing그것이 그 생성자 이름 유형의 구성원 인 상수 값으로 사용되는 경우에는 파라미터 유형이없는 Maybe a모든 타입 a. 그러나 Just생성자에는 type 매개 변수가 있습니다. 즉, 생성자로 사용될 때 type에서로 함수처럼 작동 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 참조를 통해 이러한 "값 없음"값을 처리합니다. 저명한 컴퓨터 과학자 인 토니 호 아르 (Quicksort를 발명하고 튜링 상 수상자)는이를 "십억 달러의 실수" 로 소유하고 있습니다 . 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 Integerm_xInt -> Int함수가 있으면 실제로 값이 있는지 걱정하지 않고 함수를 직접 적용 f할 수 있습니다 . 실제로 전체 리프팅 함수 체인 값에 적용 할 수 있으며 작업이 완료되면 명시 적으로 한 번만 확인 하면됩니다.fmap f m_xfMaybe IntegerInteger -> IntegerMaybe IntegerNothing

아마도 모나드로

나는 당신이 Monad아직 개념에 얼마나 익숙한 지 확신하지 못하지만 적어도 IO a전에 사용 해 왔으며 형식 서명 IO a은 현저하게 비슷합니다 Maybe a. 비록 IO그것이 당신에게 그것의 생성자를 노출하지 않습니다 따라서 만 하스켈 런타임 시스템에 의해 "실행"할 수 있다는 점에서 특별하다, 그것은 또한 아직 Functor인뿐만 아니라 Monad. 사실, a MonadFunctor몇 가지 추가 기능 가진 특별한 종류의 중요한 의미가 있지만, 여기에는 그럴만 한 곳이 아닙니다.

어쨌든 Monads IO는 "값을 산출하는 계산"을 나타내는 새로운 유형으로 맵 유형을 좋아 하고 정규 함수를 "계산하여 계산 된 값을 산출하는 계산"으로 불리는 Monad매우 fmap유사한 함수 를 통해 함수를 유형 으로 들어 올릴 수 있습니다 liftM. 함수."

그 (당신이 여기까지 읽어 경우) 당신은 아마 짐작 Maybe도이다 Monad. "값을 반환하지 못할 수있는 계산"을 나타냅니다. fmap예제 와 마찬가지로 각 단계 후 오류를 명시 적으로 확인할 필요없이 전체 계산을 수행 할 수 있습니다. 실제로 Monad인스턴스가 구성 되는 방식에 따라 Maybe값에 대한 계산 은 a 가 발생 하자마자 중지Nothing 되므로 계산 도중의 중단 또는 무가치 반환과 같습니다.

당신은 아마 쓸 수 있었다

Like I said before, there is nothing inherent to the Maybe type that is baked into the language syntax or runtime system. If Haskell didn't provide it by default, you could provide all of its functionality yourself! In fact, you could write it again yourself anyway, with different names, and get the same functionality.

Hopefully you understand the Maybe type and its constructors now, but if there is still anything unclear, let me know!


Most of the current answers are highly technical explanations of how Just and friends work; I thought I might try my hand at explaining what it's for.

A lot of languages have a value like null that can be used instead of a real value, at least for some types. This has made a lot of people very angry and been widely regarded as a bad move. Still, it's sometimes useful to have a value like null to indicate the absence of a thing.

Haskell solves this problem by making you explicitly mark places where you can have a Nothing (its version of a null). Basically, if your function would normally return the type Foo, it instead should return the type Maybe Foo. If you want to indicate that there's no value, return Nothing. If you want to return a value bar, you should instead return Just bar.

So basically, if you can't have Nothing, you don't need Just. If you can have Nothing, you do need Just.

There's nothing magical about Maybe; it's built on the Haskell type system. That means you can use all the usual Haskell pattern matching tricks with it.


Given a type t, a value of Just t is an existing value of type t, where Nothing represents a failure to reach a value, or a case where having a value would be meaningless.

In your example, having a negative balance doesn't make sense, and so if such a thing would occur, it is replaced by Nothing.

For another example, this could be used in division, defining a division function that takes a and b, and returns Just a/b if b is nonzero, and Nothing otherwise. It's often used like this, as a convenient alternative to exceptions, or like your earlier example, to replace values that don't make sense.


A total function a->b can find a value of type b for every possible value of type a.

In Haskell not all functions are total. In this particular case function lend is not total - it is not defined for case when balance is less than reserve (although, to my taste it would make more sense to not permit newBalance to be less than reserve - as is, you can borrow 101 from a balance of 100).

Other designs that deal with non-total functions:

  • throw exceptions upon checking input value does not fit the range
  • return a special value (primitive type): favourite choice is a negative value for integer functions that are meant to return Natural numbers (for example, String.indexOf - when a substring is not found, the returned index is commonly designed to be negative)
  • return a special value (pointer): NULL or some such
  • silently return without doing anything: for example, lend could be written to return old balance, if the condition for lending is not met
  • return a special value: Nothing (or Left wrapping some error description object)

These are necessary design limitations in languages that cannot enforce totality of functions (for example, Agda can, but that leads to other complications, like becoming turing-incomplete).

The problem with returning a special value or throwing exceptions is that it is easy for the caller to omit handling of such a possibility by mistake.

The problem with silently discarding a failure is also obvious - you are limiting what the caller can do with the function. For example, if lend returned old balance, the caller has no way of knowing if balance has changed. It may or may not be a problem, depending on the intended purpose.

Haskell's solution forces the caller of a partial function to deal with the type like Maybe a, or Either error a because of the function's return type.

This way lend as it is defined, is a function that doesn't always compute new balance - for some circumstances new balance is not defined. We signal this circumstance to the caller by either returning the special value Nothing, or by wrapping the new balance in Just. The caller now has freedom to choose: either handle the failure to lend in a special way, or ignore and use old balance - for example, maybe oldBalance id $ lend amount oldBalance.


Function if (cond :: Bool) then (ifTrue :: a) else (ifFalse :: a) must have the same type of ifTrue and ifFalse.

So, when we write then Nothing, we must use Maybe a type in else f

if balance < reserve
       then (Nothing :: Maybe nb)         -- same type
       else (Just newBalance :: Maybe nb) -- same type

참고URL : https://stackoverflow.com/questions/18808258/what-does-the-just-syntax-mean-in-haskell

반응형