Với mã hỗ trợ:GHC 7.8 thay ràng buộc không gõ kiểm tra
{-# LANGUAGE ExtendedDefaultRules, DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
import Data.Typeable
default(A)
data A = A deriving (Eq,Show,Typeable)
class Show a => Testable2 a where
instance (Show a, Eq a) => Testable2 a where
instance (Show a, Testable2 b) => Testable2 (a -> b) where
instance (Show a, Show b) => Show (a -> b) where show _ = "<func>"
test :: (Show p, Typeable p, Testable2 p) => p -> IO()
test = print . typeOf
Trong GHC 7.6, tôi có thể viết:
main = test (\f -> (f $))
Và đó loại séc, và in:
(A -> A) -> A -> A
Tuy nhiên, trong GHC 7,8 tôi nhận được:
Main.hs:
No instance for (Eq (a0 -> b0)) arising from a use of `test'
Nhưng, nếu tôi Refactor để:
main = let ff = \f -> (f $) in test ff
Sau đó, nó hoạt động đúng trong cả hai GHC 7.8 và GHC 7.6. Tại sao?
Logic đằng sau mã hỗ trợ là một ví dụ cho Show (a -> b)
với Show
bối cảnh để buộc kiểu mặc định nào, sau đó một cách xử lý nguyên tử mặc định (với Eq
), và là một cách di chuyển một cái gì đó trở lại hơn một ->
cho Testable2
. Mã được thiết kế để cho phép các thuộc tính QuickCheck biến đổi và được lấy từ hlint.
'main = test ($)' cung cấp cái gì? – bheklilr
Để trả lời câu hỏi của riêng tôi, trong 7,8 nó cho cùng một lỗi như 'test (\ f -> (f $))': "Không có instance cho' (Eq (a0 -> b0)) 'phát sinh từ việc sử dụng' test '" – bheklilr
Lạ lùng, nếu tôi làm 'main = test ((\ f -> (f $)) :: (a -> b) -> a -> b)' thì nó biên dịch và tạo '(A -> A) -> A -> A', nhưng nếu tôi để lại chữ ký loại tôi nhận được một lỗi. Điều này làm việc cho 'main = test (($) :: (a -> b) -> a -> b)'. – bheklilr