#haskell
Вопрос:
data D = A Int Int | B Int Char instance Show D where show (A a b) = show b show (B a b) = show b hehe :: D -> String hehe d = show u show v where (u, v) = show <
gt; case d of
A a b -> (a 1, b)
B a b -> (a 2, b)
Идея заключается в том, что я хочу применить функцию к кортежу, но она не проверяет тип, потому что вторым элементом кортежа может быть либо aInt
, либо aChar
.Вот сообщение об ошибке:
* Couldn't match expected type `Int' with actual type `Char' * In the expression: b In the expression: (a 2, b) In a case alternative: B a b -> (a 2, b) | 11 | B a b -> (a 2, b) |
Интересно, есть ли элегантное решение для решения этой проблемы?
Комментарии:
1. Вы не можете вернуть
(a 1, b)
и(a 2, b)
в ту же функцию, такb
как для первого совпадения это anInt
, тогда как для второго это aChar
.2. И вообще, почему ты гнездишься
show
? Это просто приведет к избыточным, экранированным кавычкам. И вы знаете, что fmapping над кортежем не применяет функцию ко всем элементам кортежа, верно?3. Да, я знаю, что fmapping над кортежем применяется только к последнему элементу. Что я пытаюсь здесь сделать, так это вместо того, чтобы писать шоу дважды для каждого случая, нам нужно сделать это только один раз. Просто спрашиваю, можно ли сделать это элегантно
Ответ №1:
Вы можете просто вставить шоу в дело:
hehe :: D -> String
hehe d = show u show v
where (u, v) = case d of
A a b -> (a 1, show b)
B a b -> (a 2, show b)
Если вы действительно, действительно хотите отложить шоу, вы можете использовать расширение ExistentialQuantification
языка:
data SomeShow = forall a. Show a => SomeShow a hehe :: D -> String hehe d = show u show v where (u, v) = ((SomeShow x) -> show x) <
gt; case d of
A a b -> (a 1, SomeShow b)
B a b -> (a 2, SomeShow b)
В данном случае это того не стоит.