Я немного подумал об этом, и поначалу поведение кажется странным, после некоторых размышлений, я думаю, можно оправдать это, возможно, так:
Скажем, я беру ваш второй (неудачный) пример и после некоторого массажа изамены значений Я уменьшаю это до:
data Foo = forall a. Show a => Foo { getFoo :: a }
main::IO()
main = do
let Foo x = Foo (5::Int)
putStrLn $ show x
, что приводит к ошибке:
Не удалось сопоставить ожидаемый тип 'p' с фактическим типом 'a', поскольку переменная типа 'a 'выйдет из области действия
, если будет разрешено сопоставление с образцом, какой будет тип x?ну .. тип будет конечно Int
.Однако определение Foo
говорит, что типом поля getFoo
является любого типа , который является экземпляром Show
.Int
является экземпляром Show
, но это не какой-либо тип ... это конкретный тип ... в этом отношении фактический конкретный тип значения, заключенного в Foo
, станет "видимым" (т.е. бежать) и тем самым нарушать нашу явную гарантию, что forall a . Show a =>...
Если мы сейчас посмотрим на версию кода, которая работает с использованием сопоставления с образцом в объявлении функции:
data Foo = forall a . Show a => Foo { getFoo :: !a }
unfoo :: Foo -> String
unfoo Foo{..} = show getFoo
main :: IO ()
main = do
putStrLn . unfoo $ Foo (5::Int)
Глядя на функцию unfoo
, мы видим, что там нет ничего, говорящего о том, что тип внутри Foo
- это какой-то конкретный тип .. (Int
или другой) ... в области действия этой функции все, что у нас есть, этооригинальная гарантия, что getFoo
может быть любого типа, который является экземпляром Show
.Фактический тип обернутого значения остается скрытым и непознаваемым, поэтому нет никаких нарушений каких-либо гарантий типа и наступает счастье.
PS: я забыл упомянуть, что бит Int
, конечно, был примером .. вв вашем случае тип поля getFoo
внутри значения foo
имеет тип a
, но это особый (не экзистенциальный) тип, к которому относится вывод типа GHC (а не экзистенциальный a
)в объявлении типа) .. Я только что придумал пример с конкретным типом Int
, чтобы его было легче и интуитивно понять.