약간의 알려진 사실은 충분한 언어 확장 (ghc)을 켜면 Haskell이 동적으로 형식화 된 해석 언어가된다는 것입니다! 예를 들어 다음 프로그램은 추가를 구현합니다.
{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
data Zero
data Succ a
class Add a b c | a b -> c
instance Add Zero a a
instance (Add a b c) => Add (Succ a) b (Succ c)
이것은 더 이상 Haskell처럼 보이지 않습니다. 객체를 조작하는 대신 유형을 조작합니다. 각 번호는 고유 한 유형입니다. 함수 대신에 타입 클래스가 있습니다. 기능적 종속성은 유형 간 함수로 사용할 수 있습니다.
그렇다면 코드를 어떻게 호출합니까? 우리는 다른 수업을 사용합니다
class Test a | -> a
where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
=> Test a
이것은 타입을 test
타입 4 + 3으로 설정합니다. 만약 이것을 ghci로 열면 test
실제로 타입 7이라는 것을 알 수 있습니다 .
Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))
직무
두 Peano 숫자 (음이 아닌 정수)를 곱하는 클래스를 구현하고 싶습니다. Peano 숫자는 위의 예에서 동일한 데이터 유형을 사용하여 구성됩니다.
data Zero
data Succ a
그리고 당신의 수업은 위와 같은 방식으로 평가 될 것입니다. 원하는대로 수업 이름을 지정할 수 있습니다.
바이트 단위로 무료로 원하는 ghc 언어 확장을 사용할 수 있습니다.
테스트 사례
이 테스트 사례는 클래스의 이름이 M
이고 원하는 경우 다른 이름을 지정할 수 있습니다.
class Test1 a| ->a where test1::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)=>Test1 a
class Test2 a| ->a where test2::a
instance (M Zero (Succ (Succ Zero)) a)=>Test2 a
class Test3 a| ->a where test3::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ Zero) a)=>Test3 a
class Test4 a| ->a where test4::a
instance (M (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))) (Succ (Succ (Succ Zero))) a)=>Test4 a
결과
*Main> :t test1
test1
:: Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))
*Main> :t test2
test2 :: Zero
*Main> :t test3
test3 :: Succ (Succ (Succ (Succ Zero)))
*Main> :t test4
test4
:: Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))))))))
기술 인터뷰 입력에서 영감을 얻습니다