Một thực tế ít được biết đến là nếu bạn bật đủ các phần mở rộng ngôn ngữ (ghc), Haskell sẽ trở thành một ngôn ngữ được dịch theo kiểu động! Ví dụ chương trình sau đây thực hiện bổ sung.
{-# 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)
Điều này thực sự không giống Haskell nữa. Đối với một thay vì hoạt động trên các đối tượng, chúng tôi hoạt động trên các loại. Mỗi số là loại riêng. Thay vì các hàm, chúng ta có các lớp loại. Các phụ thuộc chức năng cho phép chúng ta sử dụng chúng như các chức năng giữa các loại.
Vậy làm thế nào để chúng ta gọi mã của chúng tôi? Chúng tôi sử dụng một lớp học khác
class Test a | -> a
where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
=> Test a
Cái này đặt loại của test
loại 4 + 3. Nếu chúng ta mở cái này trong ghci, chúng ta sẽ thấy đó test
thực sự là loại 7:
Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))
Bài tập
Tôi muốn bạn thực hiện một lớp nhân hai số Peano (số nguyên không âm). Các số Peano sẽ được xây dựng bằng cách sử dụng cùng loại dữ liệu trong ví dụ trên:
data Zero
data Succ a
Và lớp học của bạn sẽ được đánh giá theo cách tương tự như trên. Bạn có thể đặt tên lớp của bạn bất cứ điều gì bạn muốn.
Bạn có thể sử dụng bất kỳ tiện ích mở rộng ngôn ngữ ghc nào bạn muốn mà không mất phí.
Các trường hợp thử nghiệm
Các trường hợp kiểm thử giả định rằng lớp của bạn được đặt tên M
, bạn có thể đặt tên cho nó một cái gì đó khác nếu bạn muốn.
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
Các kết quả
*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)))))))))))))))))
Lấy cảm hứng từ Đánh máy phỏng vấn kỹ thuật