2015-03-26 14 views
4

Я новичок в Haskell, поэтому мой вопрос, вероятно, глупо.Haskell экземпляр аналог?

Я хочу, чтобы функция,

show2 :: (Show a) => a -> String 

, который будет возвращать show a для любого a, но a если сам String. Как это реализовать?

P.S. здорово, если эта функция уже реализована где-то, но я все еще хочу увидеть пример реализации.

+4

Это вообще плохая идея, для чего это стоит. –

+0

Кстати, вы уже знаете это, но так как вы новичок: часть, которая перед символом '=>' называется контекстом (в вашем случае это 'Show a'). Поскольку есть только один, вам не нужно использовать круглые скобки. – MasterMastic

+0

@ LouisWasserman вы можете объяснить, почему? –

ответ

4

Вы можете сделать это с этим куском грязного и опасного кода:

class Showable a where 
    show2 :: a -> String 

instance Showable String where 
    show2 = id 

instance (Show a) => Showable a where 
    show2 = show 

Вам нужно -XOverlappingInstances -XFlexibleInstances -XUndecidableInstances скомпилировать и использовать его.

*Main> show2 "abc" 
"abc" 
*Main> show2 3 
"3" 
+1

'{- # LANGUAGE ... # -}' прагмы обычно лучше флагов '-X'. –

5

Вы можете использовать cast из Data.Typeable

show2 :: (Typeable a, Show a) => a -> String 
show2 s = maybe (show s) id ms 
    where ms = cast s :: Maybe String 
4

То, как Haskell разработан очень много противоположность понятию instanceof проверки. Конструкция Haskell не включает такую ​​проверку типа времени выполнения, потому что Haskell очень ориентирован на сильные гарантии времени компиляции: функция не должна более точно узнать тип своих аргументов во время выполнения, чем она знает их во время компиляции.

Это не означает, что функция не существует в ответ на Haskell-Ли демонстрирует, как это сделать, но в Haskell это неавтоматического функция обеспечивается библиотеки, не является основной частью языка (в отличие от языка, такого как Java, где это основная функция, которая всегда присутствует - вы не можете отказаться от нее!).

Обратите внимание, что даже в объектно-ориентированном программировании оператор instanceof является спорным. Многие объектно-ориентированные программисты очень сильно советуют не использовать его. Несколько примеров (из сотен):

Т он советует, чтобы все из них были одинаковыми: вместо того, чтобы тестировать тип ссылки и переключаться на разные типы поведения на основе этого, используйте полиморфизм: определите интерфейс или класс, который имеет метод для операции, которую вы хотите, и объекты, которые вы тестировали с помощью instanceof, реализуют свои собственные версии этого метода, чтобы делать правильные вещи.

Этот совет можно перевести прямолинейно в Haskell:

  1. Определите свой собственный класс типа, чтобы представить поведение, которое вы хотите
  2. Реализовать этот тип класса для каждого из типов, которые вы заинтересованы в, с правильное поведение для каждого.

Таким образом, вы могли бы сделать что-то вроде этого:

class ToString a where 
    toString :: a -> String 

instance ToString String where 
    toString str = str 

instance ToString Integer where 
    toString i = show i 

-- ... 
+0

Отлично! И могу ли я сделать что-то вроде 'instance Show a => ToString a'? –

Смежные вопросы