Có cách nào để lập trình danh sách các phiên bản của một loại lớp không? Nó đánh tôi rằng trình biên dịch phải biết thông tin này để kiểm tra và biên dịch mã, vì vậy có cách nào đó để nói với trình biên dịch: hey, bạn biết những trường hợp của lớp đó, hãy đặt một danh sách ngay tại đây (như chuỗi hoặc bất kỳ đại diện nào của chúng).Nhận danh sách các cá thể trong một loại lớp trong Haskell
Trả lời
Bạn có thể tạo các trường hợp trong phạm vi cho một lớp loại đã cho bằng cách sử dụng Mẫu Haskell.
import Language.Haskell.TH
-- get a list of instances
getInstances :: Name -> Q [ClassInstance]
getInstances typ = do
ClassI _ instances <- reify typ
return instances
-- convert the list of instances into an Exp so they can be displayed in GHCi
showInstances :: Name -> Q Exp
showInstances typ = do
ins <- getInstances typ
return . LitE . stringL $ show ins
Chạy này trong GHCi:
*Main> $(showInstances ''Num)
"[ClassInstance {ci_dfun = GHC.Num.$fNumInteger, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Integer.Type.Integer]},ClassInstance {ci_dfun = GHC.Num.$fNumInt, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Int]},ClassInstance {ci_dfun = GHC.Float.$fNumFloat, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Float]},ClassInstance {ci_dfun = GHC.Float.$fNumDouble, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Double]}]"
Một kỹ thuật hữu ích đang hiển thị tất cả các trường trong phạm vi cho một lớp học loại nhất định sử dụng GHCi.
Prelude> :info Num
class (Eq a, Show a) => Num a where
(+) :: a -> a -> a
(*) :: a -> a -> a
(-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
-- Defined in GHC.Num
instance Num Integer -- Defined in GHC.Num
instance Num Int -- Defined in GHC.Num
instance Num Float -- Defined in GHC.Float
instance Num Double -- Defined in GHC.Float
Chỉnh sửa: Điều quan trọng cần biết là trình biên dịch chỉ biết các loại lớp trong phạm vi trong bất kỳ mô-đun cụ thể nào (hoặc tại dấu nhắc ghci, v.v.). Vì vậy, nếu bạn gọi hàm showInstances
TH không có nhập, bạn sẽ chỉ nhận được các phiên từ Prelude. Nếu bạn có các mô-đun khác trong phạm vi, ví dụ: Data.Word, sau đó bạn sẽ thấy tất cả các trường hợp quá.
Dường như nó chỉ hoạt động với GHC 7 và TH 2.5. Cố gắng làm điều này trong TH 2.4.0.1 dường như không cho tôi những gì tôi muốn. Đây có phải là tính năng mới không? – mentics
Tôi đang chạy GHC 7.6.3. Đây là bản cập nhật cho câu trả lời: '[ClassInstance]' bây giờ là '[InstanceDec]'. Ngoài ra, tôi cần chạy ': set -XTemplateHaskell' trong GHCi để sao chép ví dụ. – apolune
Tôi đoán là không thể. Tôi giải thích cho bạn việc thực hiện các typeclasses (cho GHC), từ nó, bạn có thể thấy, trình biên dịch không cần phải biết loại nào là instance của một typeclass. Nó chỉ phải biết, cho dù một loại cụ thể là trường hợp hay không.
Một typeclass sẽ được dịch sang kiểu dữ liệu. Như một ví dụ, chúng ta hãy Eq
:
class Eq a where
(==),(/=) :: a -> a -> Bool
Các typeclass sẽ được dịch sang một loại từ điển, có chứa tất cả các chức năng của nó:
data Eq a = Eq {
(==) :: a -> a -> Bool,
(/=) :: a -> a -> Bool
}
Mỗi chế typeclass sau đó được dịch ra một cuộc tranh cãi thêm chứa từ điển:
elem :: Eq a => a -> [a] -> Bool
elem _ [] = False
elem a (x:xs) | x == a = True
| otherwise = elem a xs
trở thành:
elem :: Eq a -> a -> [a] -> Bool
elem _ _ [] = False
elem eq a (x:xs) | (==) eq x a = True
| otherwise = elem eq a xs
Điều quan trọng là từ điển sẽ được chuyển qua khi chạy. Hãy tưởng tượng, dự án của bạn chứa nhiều mô-đun. GHC không phải kiểm tra tất cả các mô-đun cho các trường hợp, nó chỉ cần tra cứu, cho dù một cá thể được định nghĩa ở bất kỳ đâu.
Nhưng nếu bạn có sẵn nguồn, tôi đoán kiểu cũ grep
cho các trường hợp sẽ là đủ.
Không chính xác. Trình biên dịch chỉ cần biết nếu một kiểu cụ thể là một cá thể, tuy nhiên bất cứ lúc nào trình biên dịch có thể liệt kê tất cả các cá thể trong phạm vi và tạo ra danh sách mong muốn. GHCi sẽ làm điều này nếu bạn sử dụng ': info Num' chẳng hạn. –
Không thể tự động thực hiện việc này cho các lớp hiện có. Đối với lớp học của riêng bạn và các trường hợp của bạn, bạn có thể làm điều đó. Bạn sẽ cần khai báo mọi thứ thông qua Template Haskell (hoặc có lẽ là bán dẫn) và nó sẽ tự động tạo ra một số cấu trúc dữ liệu lạ mã hóa các cá thể đã khai báo. Xác định cấu trúc dữ liệu lạ và làm cho mẫu Haskell làm điều này là các chi tiết còn lại cho bất kỳ ai có trường hợp sử dụng cho chúng.
Có lẽ bạn có thể thêm một số mẫu Haskell hoặc ma thuật khác vào bản dựng của bạn để bao gồm tất cả các tệp nguồn dưới dạng văn bản có sẵn tại thời gian chạy (chuỗi chương trình c.f.). Sau đó, chương trình của bạn sẽ 'grep bản thân' ...
này sẽ chạy vào rất nhiều vấn đề càng sớm càng bạn nhận được tờ khai dụ như
instance Eq a => Eq [a] where
[] == [] = True
(x:xs) == (y:ys) = x == y && xs == ys
_ == _ = False
và
instance (Eq a,Eq b) => Eq (a,b) where
(a1,b1) == (a2,b2) = a1 == a2 && b1 == b2
cùng với một ví dụ cụ thể (ví dụ: instance Eq Bool
).
Bạn sẽ nhận được một danh sách vô hạn các trường hợp cho Eq
-Bool
, [Bool]
, [[Bool]]
, [[[Bool]]]
và như vậy, (Bool,Bool)
, ((Bool,Bool),Bool)
, (((Bool,Bool),Bool),Bool)
etcetera, cùng với sự kết hợp khác nhau của các như ([((Bool,[Bool]),Bool)],Bool)
và vân vân.Nó không rõ ràng làm thế nào để đại diện cho những trong một String
; ngay cả một danh sách của TypeRep
sẽ yêu cầu một số liệt kê khá thông minh.
Trình biên dịch thể (cố gắng) suy ra liệu một loại là một thể hiện của Eq
cho bất kỳ loại nào đó, nhưng nó không đọc trong tất cả các tờ khai dụ trong phạm vi và sau đó chỉ cần bắt đầu suy luận tất cả các trường có thể, kể từ điều đó sẽ không bao giờ kết thúc!
Câu hỏi quan trọng là tất nhiên, bạn cần điều này để làm gì?
Xem tài liệu mẫu Haskell: http://hackage.haskell.org/packages/archive/template-haskell/2.5.0.0/doc/html/Language-Haskell-TH.html
Sử dụng reify
, bạn có thể nhận được một kỷ lục Info, mà cho một lớp học bao gồm danh sách các trường hợp. Bạn cũng có thể sử dụng trực tiếp isClassInstance
và classInstances
.
- 1. OOP python - loại bỏ cá thể lớp khỏi danh sách
- 2. Nhận danh sách tất cả các lớp đang được tải trong một cá thể JVM cụ thể
- 3. Nhận danh sách phụ trong Haskell
- 4. Haskell tính danh sách loại
- 5. Làm việc trên danh sách các danh sách trong Haskell
- 6. Ghép nối các danh sách trong Haskell
- 7. nhiều tham số loại trong các loại lớp haskell
- 8. Có một bách khoa toàn thư/danh sách các lớp học phổ biến trong Haskell không?
- 9. Haskell: lọc danh sách heterogenous theo loại
- 10. Loại bỏ đường cú pháp: Danh sách hiểu trong Haskell
- 11. Không thể đọc một const trong một cá thể lớp?
- 12. Các loại nên được sử dụng như thế nào trong các lớp loại Haskell?
- 13. Ổ đĩa danh sách Haskell trong Windows
- 14. Các danh tiếng của một danh sách - Haskell
- 15. Ruby AWS - Tạo lập trình danh sách các loại cá thể AWS có sẵn
- 16. Tìm tất cả các cá thể của một lớp trong khi gỡ lỗi trong Eclipse
- 17. Nhận một cá thể đối tượng mới từ một loại
- 18. Lặp lại một danh sách các loại
- 19. Nhận danh sách phụ từ một danh sách trong Freemarker
- 20. danh sách Giáo Hội trong Haskell
- 21. Danh sách trong Haskell: loại dữ liệu hoặc loại dữ liệu trừu tượng?
- 22. Giải thích Loại Lớp học trong Haskell
- 23. Clojure thành ngữ để "loại bỏ" một cá thể đơn lẻ từ nhiều người trong danh sách là gì?
- 24. Học Haskell: danh sách hiểu trong C#
- 25. Bạn có thể nhận ra danh sách vô hạn trong chương trình Haskell không?
- 26. C/C++ Có thể nhận được một "danh sách" các thành viên cá thể bằng cách truy vấn một lớp học?
- 27. Chia nhỏ danh sách trong haskell
- 28. sáp nhập hai danh sách trong Haskell
- 29. php Đặt chức năng ẩn danh trong một cá thể
- 30. Lưu trữ các loại khác nhau trong danh sách?
Thực ra, trình biên dịch không biết trường hợp nào được xác định. Điều duy nhất nó có thể làm, là kiểm tra xem một loại là trường hợp của một typeclass. – fuz