Haskell printf는 어떻게 작동합니까?
Haskell의 유형 안전성은 종속 유형 언어 에 뒤지지 않습니다 . 그러나 Text.Printf 에는 다소 유형이 이상한 것처럼 보이는 깊은 마법이 있습니다.
> printf "%d\n" 3
3
> printf "%s %f %d" "foo" 3.3 3
foo 3.3 3
이것 뒤에 숨겨진 깊은 마법은 무엇입니까? Text.Printf.printf
함수가 이와 같은 가변 인수를 어떻게 취할 수 있습니까?
Haskell에서 가변 인수를 허용하는 데 사용되는 일반적인 기술은 무엇이며 어떻게 작동합니까?
(참고 :이 기술을 사용하면 일부 형식 안전성이 손실되는 것 같습니다.)
> :t printf "%d\n" "foo"
printf "%d\n" "foo" :: (PrintfType ([Char] -> t)) => t
트릭은 유형 클래스를 사용하는 것입니다. 의 경우 printf
키는 PrintfType
유형 클래스입니다. 메서드를 노출하지 않지만 중요한 부분은 어쨌든 형식에 있습니다.
class PrintfType r
printf :: PrintfType r => String -> r
따라서 printf
오버로드 된 반환 유형이 있습니다. 사소한 경우에는 추가 인수가 없기 때문에으로 인스턴스화 할 수 있어야 r
합니다 IO ()
. 이를 위해 인스턴스가 있습니다.
instance PrintfType (IO ())
다음으로 가변 개수의 인수를 지원하려면 인스턴스 수준에서 재귀를 사용해야합니다. 경우 있도록 특히 우리는 인스턴스를 필요 r
입니다 PrintfType
, 함수 타입 x -> r
도있다 PrintfType
.
-- instance PrintfType r => PrintfType (x -> r)
물론 우리는 실제로 형식을 지정할 수있는 인수 만 지원하려고합니다. 이것이 두 번째 유형 클래스 PrintfArg
가 들어오는 곳입니다. 따라서 실제 인스턴스는
instance (PrintfArg x, PrintfType r) => PrintfType (x -> r)
다음은 Show
클래스 에서 여러 인수를 가져 와서 인쇄 하는 단순화 된 버전입니다 .
{-# LANGUAGE FlexibleInstances #-}
foo :: FooType a => a
foo = bar (return ())
class FooType a where
bar :: IO () -> a
instance FooType (IO ()) where
bar = id
instance (Show x, FooType r) => FooType (x -> r) where
bar s x = bar (s >> print x)
여기서는 bar
더 이상 인수가 없을 때까지 재귀 적으로 생성되는 IO 액션을 취합니다.이 시점에서 단순히 실행합니다.
*Main> foo 3 :: IO ()
3
*Main> foo 3 "hello" :: IO ()
3
"hello"
*Main> foo 3 "hello" True :: IO ()
3
"hello"
True
QuickCheck는 또한 동일한 기술을 사용합니다. 여기서 Testable
클래스에는 기본 케이스에 대한 인스턴스 Bool
가 있고 Arbitrary
클래스 에서 인수를받는 함수에 대한 재귀 인스턴스 가 있습니다 .
class Testable a
instance Testable Bool
instance (Arbitrary x, Testable r) => Testable (x -> r)
참고 URL : https://stackoverflow.com/questions/7828072/how-does-haskell-printf-work
'programing tip' 카테고리의 다른 글
node.js의 ES6 변수 가져 오기 이름? (0) | 2020.08.24 |
---|---|
"2016-02-16"이 "2016-02-16 00:00"과 같지 않은 이유는 무엇입니까? (0) | 2020.08.24 |
Javascript 웹 앱 및 Java 서버, Maven에서 모두 빌드하거나 웹 앱용 Grunt를 사용 하시겠습니까? (0) | 2020.08.24 |
열거 형 유형에 대한 네임 스페이스-모범 사례 (0) | 2020.08.24 |
setAccessible을 "합법적 인"용도로만 제한하는 방법은 무엇입니까? (0) | 2020.08.24 |