Как сказано в названии, я заинтересован в использовании Show a
в контексте, в котором у меня есть Show (a,b)
. Эта проблема легко возникает с GADT следующим образом:
data PairOrNot a where
Pair :: (b,c) -> PairOrNot (b,c)
Not :: a -> PairOrNot a
showFirstIfPair :: Show a => PairOrNot a -> String
showFirstIfPair (Not a) = show a
showFirstIfPair (Pair (b,c)) = show b
Ошибка:
Could not deduce (Show b) arising from a use of ‘show’
from the context (Show a)
bound by the type signature for
showFirstIfPair :: Show a => PairOrNot a -> String
at app/Main.hs:24:20-50
or from (a ~ (b, c))
bound by a pattern with constructor
Pair :: forall b c. (b, c) -> PairOrNot (b, c),
in an equation for ‘showFirstIfPair’
at app/Main.hs:26:18-27
Possible fix:
add (Show b) to the context of the data constructor ‘Pair’
In the expression: show b
In an equation for ‘showFirstIfPair’:
showFirstIfPair (Pair (b, c)) = show b
Я бы подумал, что объявление экземпляра instance (Show a, Show b) => Show (a,b)
доказывает Show element
, но я также могу представить, что проблема также как-то связана с тем, как механизм классов типов реализуется во время выполнения.
Я обнаружил, что если мы можем изменить определение класса, это можно решить с помощью:
class Show' a where
show' :: a -> String
unpair :: a -> Dict (a ~ (b,c)) -> Dict (Show' b, Show' c)
-- An example non-pair instance
instance Show' Int where
show' i = ""
unpair = undefined -- This is OK, since no one can construct Dict (Int ~ (b,c))
instance (Show' a, Show' b) => Show' (a,b) where
show' (a,b) = ""
unpair _ Dict = Dict -- In this context we have access to Show' for elems
Затем на сайте использования мы явно получаем словарь:
showFirstIfPair :: Show' a => PairOrNot a -> String
showFirstIfPair (Not a) = show' a
showFirstIfPair (Pair a@(b,c)) =
case unpair a Dict of -- This is a Dict (a~(b,c))
Dict -> show' b -- This is Dict (Show' b,Show' c)
Мне было интересно, есть ли ненавязчивый (или просто другой) способ получения Show element
. Если нет, не могли бы вы объяснить, почему именно возникает эта проблема?
(Show b, Show c)
, чтобы построить словарьShow (b, c)
. Итак, в точке, где вы создаетеPair
, вы можете вместо этого просто извлечь первый элемент - person Benjamin Hodgson♦   schedule 22.09.2016Show a, Show b => ...
, но в вашем коде есть толькоShow a => ...
, поэтому возникает ошибка о невозможности вывестиShow b
. - person Lee   schedule 22.09.2016Show a, Show b => Show (a,b)
означает, чтоShow a
иShow b
вместе даютShow (a,b)
, но это не обязательно означает противоположное. Например, рассмотрим два типаX, Y
сinstance Show (X, Y)
- у вас не обязательно есть здесьinstance (Show X)
, потому чтоshow
может бытьconst ""
. Вашаunpair
функция дает подтверждение того свойства, которое вы хотите, и это именно то, что вы должны сделать, если хотите использовать указанное свойство. - person user2407038   schedule 22.09.2016Z
истинно тогда и только тогда, когдаX
иY
, неZ
подразумевает иX
, иY
? Может, мне не следует думать об этом как о логическом утверждении. - person enobayram   schedule 22.09.2016OverlappingInstances
был включен, кто-то мог бы определить мошенникаinstance Show (X, Y)
безShow X
илиShow Y
. - person enobayram   schedule 22.09.2016A /\ B => C
означает, что иA
, иB
вместе являются достаточным условием дляC
, что ничего не говорит о том, что происходит в отношенииA
иB
, когдаC
определенно выполняется. Он не утверждает, чтоC
выполняется тогда и только тогда, когдаA /\ B
. То, что вы описываете, обычно пишетсяA /\ B <=> C
илиA /\ B == C
. - person user2407038   schedule 22.09.2016(Show a, a ~ (b,c))
и мне нужноShow b
- person enobayram   schedule 22.09.2016OverlappingInstances
где-то для конкретного примера, который я привел, но дело в том, что компилятор не может предположить, чтоShow (a,b)
пришел из(Show a, Show b)
, независимо от того, что вы делаете, потому что это предположение просто не звук. Это всего лишь предположение об открытом мире для классов типов в несколько хитрой форме. - person user2407038   schedule 22.09.2016Show a
изShow (a,b)
. Но Haskell хочет допустить возможность перекрытия, поэтому он должен запретить этот необоснованный вывод. - person chi   schedule 22.09.2016f x y
, вы не можете ожидать восстановленияx
илиy
. - person dfeuer   schedule 23.09.2016