xem xét mã này:Thêm một trường hợp không sử dụng sửa chữa một lỗi loại
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Foo where
class Foo a
class SomeClass a
instance {-# OVERLAPPABLE #-} (Foo a) => SomeClass a
bar :: (SomeClass a) => a -> Int
bar = const 0
foo :: (SomeClass a) => a -> Int
foo t = let x = bar t in x
Ở đây, foo
cuộc gọi bar
, và sẽ có thể làm như vậy bằng cách sử dụng SomeClass
hạn chế trong bối cảnh của nó. Thay vào đó, GHC giả định nó phải làm như vậy bằng cách sử dụng Foo a => SomeClass a
dụ:
Foo.hs:16:17:
Could not deduce (Foo a) arising from a use of ‘bar’
from the context (SomeClass a)
bound by the type signature for foo :: SomeClass a => a -> Int
at Foo.hs:15:8-32
Possible fix:
add (Foo a) to the context of
the inferred type of x :: Int
or the type signature for foo :: SomeClass a => a -> Int
In the expression: bar t
In an equation for ‘x’: x = bar t
In the expression: let x = bar t in x
Có hai cách để sửa lỗi này:
- Trong
foo
, thay đổilet x = bar t in x
đểbar t
- Phụ thêm dòng
instance SomeClass Int
để tôi chương trình
Điều gì đang xảy ra ở đây? Tại sao sự cố này xảy ra và tại sao các bản sửa lỗi này hoạt động?
Ví dụ này, tất nhiên, được đơn giản hóa bởi vấn đề thực tế của tôi. Tôi đã gặp nó trong quá trình làm việc trên khung công tác Cubix để chuyển đổi đa ngôn ngữ (arxiv.org/pdf/1707.04600).
Vấn đề thực tế của tôi liên quan đến một hàm có ràng buộc InjF f IdentL FunctionExpL
("f là ngôn ngữ có thể sử dụng mã định danh để biểu thị hàm trong cuộc gọi hàm"). Tôi có một trường hợp (có thể chồng chéo) (FunctionIdent :<: f) => InjF f IdentL FunctionExpL
, mà máy đánh chữ thu giữ, cho tôi một lỗi giả mạo Could not deduce FunctionIdent :<: f
.
Lỗi này vẫn tồn tại ngay cả khi có một trường hợptrong phạm vi cho một Foo
cụ thể, do đó, câu trả lời của leftaroundabout, dự đoán rằng trường hợp khác cần khắc phục sự cố, không phải là toàn bộ câu chuyện.
'{- # OVERLAPPABLE # -}' và '{- # LANGUAGE FlexibleContexts # -}' không ảnh hưởng gì cả. Một cách khác để biên dịch: thêm một 'x :: Int' vào liên kết' let'. – Alec
Có lẽ điều silliest là nó cũng typechecks khi có _no dụ tại all_ trong module ... – leftaroundabout