У меня есть функция ip
, которую я не могу изменить:Работа с `show` в Haskell
ip = show a ++ show b ++ show C++ show d
, и я должен определить a
, b
, c
и d
так, что:
GHCi> ip
"127.224.120.12"
. Как мне это сделать?
У меня есть функция ip
, которую я не могу изменить:Работа с `show` в Haskell
ip = show a ++ show b ++ show C++ show d
, и я должен определить a
, b
, c
и d
так, что:
GHCi> ip
"127.224.120.12"
. Как мне это сделать?
Есть разные способы, которыми вы можете это сделать. В любом случае экземпляры по умолчанию Show
, вероятно, вам не подходят, это ядро проблемы: вы захотите определить свой собственный тип с помощью настраиваемого экземпляра Show
. Общий способ переопределения типов с помощью настраиваемых экземпляров (или скрытых экземпляров) использует newtype
.
Мы можем использовать другой Show
экземпляр с String
-как типа, так что нет никакой возможности избежать или добавление "
:
newtype MyStr = MyStr String
instance Show MyStr where
show (MyStr s) = s
ip a b c d = show a ++ show b ++ show C++ show d
a = MyStr "127."
b = MyStr "224."
c = MyStr "120."
d = MyStr "12"
main = print $ ip a b c d
Другой возможностью было бы определить альтернативу для Int
типа, где .
прилагается при использовании show
. Затем мы используем этот тип для первых трех аргументов ip
и используем обычный Int
для последнего аргумента (a
, b
, c
и d
могут иметь разные типы).
newtype MyInt = MyInt Int
instance Show MyInt where
show (MyInt s) = show s ++ "."
ip a b c d = show a ++ show b ++ show C++ show d
a = MyInt 127
b = MyInt 224
c = MyInt 120
d = 12
main = print $ ip a b c d
Обратите внимание, что в обоих случаях решение является немного взломанным, но это связано с характером проблемы. Обычно вы хотели бы, чтобы экземпляры Show
были скорее техническими, чем «стилистическими»: вы хотите показать всю информацию о значении, предпочтительно таким образом, который может быть считан с помощью read
(путем определения соответствующего примера Read
). Для вывода стилей более подходящий принтер.
Я почти уверен, что это не то решение, которое ожидалось, но оно умно, и оно работает, поэтому спасибо. – Chiffa
@Chiffa: Мне было бы интересно услышать о ожидаемом решении, если оно совсем другое. Я не могу думать иначе, чем использовать пользовательский экземпляр «Show». –
Я обязательно отправлю его, как только получу. – Chiffa
Ваша ip
функция будет отличаться в зависимости от того, что вы хотите использовать для a
, b
, c
и d
:
Если вы выбираете строки:
ip1 :: String -> String -> String -> String -> String
ip1 a b c d = a ++ "." ++ b ++ "." ++ C++ "." ++ d
и если вы выбираете Ints:
ip2 :: Int -> Int -> Int -> Int -> String
ip2 a b c d = show a ++ "." ++ show b ++ "." ++ show C++ "." ++ show d
Обновление
Может быть, эти примеры создания новых типов и показать примеры их помогут:
data Foo = F String
instance Show Foo where
show (F string) = "a string of length " ++ show (length string)
data Bar = B Double
instance Show Bar where
show (B adouble) = if adouble > 0 then "(positive)" else "(not positive)"
a = F "abc"
b = B 14.0
Тогда:
show a ++ show b
приводит:
"a string of length 3(positive)"
У меня нет контроля над 'show', я могу предоставить только правильные аргументы. В противном случае ваши решения великолепны, и я уже думал об этом. – Chiffa
Вы знаете, что такое типы a, b, c, d. Вы не можете определить 'ip', где иногда' a' является Int, а иногда и String. Покажите нам больше того, что вы пытаетесь сделать. – ErikR
Я пытаюсь выбрать 'a',' b' и т. Д. Таким образом, что 'show' не добавляет к ним лишних символов. – Chiffa
С числами с плавающей точкой:
> let ip a b c d = show a ++ show b ++ show C++ show d
> ip 127.2 24.12 0.1 2
"127.224.120.12"
Есть несколько способов сделать это. Какая у вас проблема? – dfeuer
Концептуальные. Если я определяю, скажем, 'a =" 127 ",' show' добавляет все кавычки и escape-последовательности, а результат конкатенации неверен. Если я делаю 'a = 127.', Haskell рассматривает точку как функцию. И так далее. – Chiffa
А какой другой тип вы могли бы использовать? –