Haskell instanceof analogue?

ぐ巨炮叔叔 提交于 2019-12-10 13:44:07

问题


I am new to Haskell, so my question is probably stupid.

I want a function

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

which would return show a for any a, but a if a is itself String. How can I implement it?

P.S. it is great if this function is already implemented somewhere, but I still want to see an example of the implementation.


回答1:


You can do this with this piece of dirty and dangerous code:

class Showable a where
  show2 :: a -> String

instance Showable String where
  show2 = id

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

You need -XOverlappingInstances -XFlexibleInstances -XUndecidableInstances to compile and use it.

*Main> show2 "abc"
"abc"
*Main> show2 3
"3"



回答2:


You can use cast from Data.Typeable

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



回答3:


The way that Haskell is designed is very much opposed to the concept of an instanceof check. Haskell's design does not incorporate this sort of runtime type check, because Haskell is very focused on strong compilation-time guarantees: a function should not be able to learn the type of its arguments at runtime any more precisely than it knows them at compilation time.

This doesn't meant that the feature doesn't exist in Haskell—Lee's answer demonstrates how to do it—but in Haskell this is an opt-in feature provided by a library, not a core part of the language (unlike a language like Java, where it's a core feature that's always present—you can't opt out of it!).

Note that even in object-oriented programming the instanceof operator is controversial. Many object-oriented programmers very strongly advise against its use. A few examples (out of hundreds):

  • use of "Instance of" in java
  • Avoiding instanceof in Java
  • http://smsohan.com/blog/2011/11/01/using-instanceof-is-mostly-code-smell/
  • http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
  • http://www.javapractices.com/topic/TopicAction.do?Id=31
  • http://www.artima.com/interfacedesign/PreferPoly.html

The advise in all of these tends to be the same: instead of using testing the type of a reference and switching to different behaviors based on it, use polymorphism: define an interface or class that has a method for the operation you want, and have the objects that you were testing with instanceof implement their own versions of that method to do the right thing.

This advice can be translated straightforwardly to Haskell:

  1. Define your own type class to represent the behavior you want
  2. Implement this type class for each of the types that you're interested in, with the correct behavior for each.

So, you could do something like this:

class ToString a where
    toString :: a -> String

instance ToString String where
    toString str = str

instance ToString Integer where
    toString i = show i

-- ...


来源:https://stackoverflow.com/questions/29284765/haskell-instanceof-analogue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!