Vì vậy, nói rằng tôi có một lớp:chức năng đa hình về hiện sinh loại
class C a where
reduce :: a -> Int
Bây giờ tôi muốn để đóng gói nó trong một kiểu dữ liệu:
data Signal = forall a. (C a) => Signal [(Double, a)]
Nhờ có sự định lượng hiện sinh, tôi có thể gọi Các phương thức C trên Tín hiệu, nhưng Tín hiệu không hiển thị thông số loại:
reduceSig :: Signal -> [(Double, Int)]
reduceSig (Signal sig) = map (second reduce) sig
Vì C có một số phương pháp tự nhiên của tôi bước tiếp theo là kéo chức năng 'giảm' để tôi có thể thay thế bất kỳ phương thức nào:
mapsig :: (C a) => (a -> a) -> Signal -> Signal
mapsig f (Signal sig) = Signal (map (second f) sig)
Lỗi loại! Không thể suy ra (a1 ~ a). Trên suy nghĩ thêm, tôi nghĩ rằng những gì nó nói là 'f' là một chức năng trên một số trường hợp của C, nhưng tôi không thể đảm bảo nó là cùng một ví dụ của C như trong các tín hiệu, vì các thông số loại được che dấu! Tôi muốn, tôi hiểu rồi.
Vậy điều này có nghĩa là không thể khái quát hóa reduceSig? Tôi có thể sống với điều này, nhưng tôi được sử dụng để tự do bao gồm các chức năng trong haskell nó cảm thấy lạ để có nghĩa vụ phải viết boilerplate. Mặt khác, tôi không thể nghĩ ra bất kỳ cách nào để thể hiện rằng một loại là bằng loại bên trong của tín hiệu, ngắn cho tín hiệu một tham số kiểu.
Nhân tiện, trừ khi 'C' chứa nhiều hơn bạn có ở đây, loại' Tín hiệu' của bạn tương đương với 'dữ liệu Tín hiệu = Tín hiệu [(Đôi, Int) ] '! Vì vậy, không có lợi thế để sử dụng một loại tồn tại ở đây, trừ khi đây là một vấn đề đơn giản hóa (xem thêm: [1] (http://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/) , [2] (http://www.haskell.org/haskellwiki/FAQ#I.27m_making_an_RPG._Should_I_define_a_type_for_each_kind_of_monster.2C_and_a_type_class_for_them.3F), mặc dù các tình huống mà chúng giải quyết không hoàn toàn tương tự). – ehird
Vâng, C có một loạt các phương pháp, tôi chỉ cố gắng đơn giản hóa cho ví dụ. Nhưng khi bạn chỉ ra, đơn giản hóa quá nhiều và lý do toàn bộ biến mất :) –