숫자 리터럴 (즉, 하스켈 코드에 숫자를 입력하는 것)은 일부 고정 유형이 아닙니다. 그것들은 다형성입니다. 그들은 어떤 맥락에서 그들이 구체적인 유형을 요구하는 평가를 받아야합니다.
그래서 식
5.0 * (3 - 1)
는
Float
하여
Int
승산
하지이다.
5.0
은
Fractional
유형이어야하며,
3
및
1
은 각각
Num
유형입니다.
3 - 1
은 3과 1 모두가
동일
Num
유형이어야한다는 것을 의미하지만, 우리는 여전히 어떤 특정한 제약 조건을 가지고 있지 않습니다. 빼기의 결과는 같은 유형입니다.
*
은 두 인수가 모두 같은 형식이어야하며 결과도 같은 형식이어야 함을 의미합니다. 5.0
은 Fractional
유형이므로 (3 - 1)
도 입력해야합니다. 3
, 1
및 (3 - 1)
은 Num
유형이어야하지만 Fractional
유형은 모두 Num
유형이기 때문에이 요구 사항은 충돌하지 않습니다.
결과적 전체 표현식이 5.0 * (3 - 1)
Fractional
일부 타입, 및 5.0
, 3
및 1
모두 동일한 타입이다. 당신이 볼 수 GHCi의 :t
명령을 사용할 수 있습니다 : 실제로 이 그 표현을 평가하기 위해
Prelude> :t 5.0 * (3 - 1)
5.0 * (3 - 1) :: Fractional a => a
하지만, 우리는 몇 가지 구체적인 유형 그렇게해야합니다.이것을 평가하여 Float
, Double
또는 다른 특정 Fractional
유형을 필요로하는 함수에 전달하면 하스켈은 그 중 하나를 선택합니다. 특정 유형이어야하는 다른 컨텍스트없이 표현식을 평가하는 경우 Haskell은 자동으로 하나의 기본 규칙을 선택합니다 (기본 규칙이 적용되지 않으면 모호한 유형 변수에 대한 유형 오류가 발생합니다). 내가 5.0 * (3 - 1)
을 평가 한 위
는
Prelude> 5.0 * (3 - 1)
10.0
Prelude> :t it
it :: Double
, 다음 GHCi는 항상 평가 된 마지막 값에 바인딩 마법 it
변수의 유형에 대해 물었다. 이것은 GHCi가 내 Fractional a => a
유형을 Double
으로 기본값으로 설정하여 표현식의 값이 10.0
임을 계산합니다. 이 평가를 수행 할 때 Double
초 만 곱셈 (그리고 빼기) 한 결과 Double
에 Int
을 곱하지 않았습니다.
자, 당신은 서로 다른 종류의 수 있습니다처럼 여러 숫자 리터럴 할 때 무슨 일인지입니다. 그러나 귀하의 test
함수는 리터럴을 곱하는 것이 아니라, 알려진 유형의 곱셈 변수입니다. Haskell에서 Int
에 Float
을 곱할 수 없습니다. *
연산자는 Num a => a -> a -> a
유형을 가지고 있기 때문에 동일한 숫자 유형의 두 값을 취하여 그 유형의 결과를 제공합니다. Int
에 Int
을 곱하면 , Float
이면 Float
이되고 Float
이됩니다. Int
에 Float
을 곱하면 ???
이됩니다.
다른 언어는 경우에 따라 변환 함수에 대한 호출을 암시 적으로 삽입하여 이러한 종류의 작업을 지원합니다. Haskell never은 형식을 암시 적으로 변환하지만 변환 함수가 있습니다. 원할 경우 명시 적으로 호출하면됩니다. 당신이 서명을 추가하기 전에,
test :: Float -> Int -> Int -> Float
test a b c = a * fromIntegral (b - c)
출처
2013-09-26 04:57:44
Ben
"적절한 컴파일러에서는 자동 강제 변환이 없습니다."- 그러나 숫자 리터럴의 강요가 있습니다 ("ghci"와 동일). – fjarri
아, 맞아. 리터럴 강제가 여기에 작용하지 않습니다. 내가 편집 할게. –
실제로 컴파일 된 모듈보다 GHCi에서 부동 소수점 또는 정수로 간주되는 숫자가 문제가 될 가능성이 훨씬 큽니다. 두 경우 모두 숫자의 유형을 파악할 때 전체 "편집 단위"에서 숫자가 사용되는 방식이 고려되지만 GHCi에서 "편집 단위"는 한 번에 하나씩 취한 각 입력 행입니다. 따라서 숫자 형이 기본값으로 설정되는 방식은 REPL 스타일 개발을 위해 수행되지 않습니다. 실제로 REPL에서는 꽤 고통 스럽습니다. – Ben