Как сделать так, чтобы эта функция Haskell проверяла тип

#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)

Идея заключается в том, что я хочу применить функцию к кортежу, но она не проверяет тип, потому что вторым элементом кортежа может быть либо a Int , либо a Char .

Вот сообщение об ошибке:

     * 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 как для первого совпадения это an Int , тогда как для второго это a Char .

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)

В данном случае это того не стоит.