Được rồi. Vấn đề ở đây khá trừu tượng. Chịu với tôi.Thuyết phục trình biên dịch rằng có một chuỗi cá thể hợp lệ
Tôi có một nhóm "Đơn vị", mỗi đơn vị có một số thuộc tính nhất định. Các tính chất này được định nghĩa trong lớp Seq
, như thế này:
class Seq a x y where
break :: x -> (a, y)
build :: a -> y -> x
Về mặt lý thuyết, loại a
là loại quan trọng, x
là bối cảnh sử dụng để tạo ra một a
, và y
là bối cảnh sử dụng để tạo ra bất kỳ thêm Seq
trường hợp. break
ngắt Seq
xuống, build
cho phép bạn tạo lại.
Trên cá nhân Seq
trường hợp, tính năng này hoạt động tốt. Tuy nhiên, tôi cũng có một nhà xây dựng dữ liệu mà trông như thế này:
data a :/: b = a :/: b deriving (Eq, Ord)
infixr :/:
Mục tiêu của toàn bộ hoạt động này là để có thể soạn Seq
trường.
Ví dụ, nếu tôi có a
, b
và c
tất cả các trường của Seq
mà a
'bối cảnh của nguồn cấp dữ liệu vào b
và b
' s nguồn cấp dữ liệu vào c
, sau đó tôi tự động nên có một trường hợp Seq
cho a :/: b :/: c
. Lớp để thiết lập điều này khá đơn giản thông qua kiểu dữ liệu đệ quy:
instance (Seq a x y, Seq b y z) => Seq (a :/: b) x z where
break x = let
(a, y) = break x :: (a, y)
(b, z) = break y :: (b, z)
in (a :/: b, z)
build (a :/: b) z = let
y = build b z :: y
x = build a y :: x
in x
Vấn đề là tôi không thể sử dụng nó. Nếu tôi xác định sau ba Seq
trường hợp:
data Foo
instance Seq Foo Integer Bool
data Bar
instance Seq Bar Bool Bar
data Baz
instance Seq Baz Bar()
(chi tiết thực hiện redacted, xem here để biết thêm)
và một cái giếng, đánh máy break
chức năng:
myBreak :: Integer -> (Foo :/: Bar :/: Baz)
myBreak = fst . break' where
break' = break :: Integer -> (Foo :/: Bar :/: Baz,())
sau đó tôi không thể thậm chí biên dịch:
No instances for (Seq Foo Integer y, Seq Bar y y1, Seq Baz y1())
arising from a use of `break'
Possible fix:
add instance declarations for
(Seq Foo Integer y, Seq Bar y y1, Seq Baz y1())
In the expression: break :: Integer -> (Foo :/: (Bar :/: Baz),())
In an equation for break':
break' = break :: Integer -> (Foo :/: (Bar :/: Baz),())
In an equation for `myBreak':
myBreak
= fst . break'
where
break' = break :: Integer -> (Foo :/: (Bar :/: Baz),())
Nó nhìn tôi như myBreak
không thể chắc chắn rằng có một "chuỗi làm việc" của các ngữ cảnh từ Foo → Bar → Baz. Làm thế nào tôi có thể thuyết phục trình biên dịch rằng điều này được đánh máy tốt?
Đây là một trong những chuyến du ngoạn đầu tiên của tôi vào lập trình loại, vì vậy tôi chắc chắn sẽ phá vỡ một số quy tắc được thiết lập tốt. Tôi khá tò mò về những gì tôi đang làm sai ở đây, nhưng tôi cũng mở để gợi ý về cách đạt được mục tiêu của mình tốt hơn.
Tôi sẽ cố gắng suy nghĩ thêm về điều này, nhưng chỉ cần đoán, thường là khi bạn có lỗi "không có ví dụ ..." trong trường hợp tìm kiếm là đa hình (như 'Seq Foo Integer y' trong trường hợp của bạn) và bạn không có nghĩa là, phụ thuộc chức năng có thể làm cho nó tốt hơn. – Owen