这是我想要的:
f n = case n of String -> "string" _ -> "other"
或者其他的东西。f
如果要用字符串调用,我想映射到文字“字符串”,否则要映射为“其他”。这不能像我正在做的那么难。
If you're coming from JS and Python it's understandable you think that something that this should be possible – after all, in those languages a type is essentially a particular property of a value. But that's not at all how the Haskell type system works! In fact, types and values belong to completely separate “universes”: types only exist at compile time, values only at runtime. It's still true that every value belongs to a type, but this information is already completely resolved at compile-time. At runtime it is generally not necessary to dispatch on types, because the compiler has already done that earlier, and it can never be possible that a value of type other than the valid one is ever passed in. So this would always be redundant. In fact the type information is removed before the program is run.
So in the direct sense, what you're trying to accomplish is indeed impossible. Or, cynically speaking, it's trivial:
f :: String -> String f _ = "string"
Generally, if you find yourself wanting to runtime-dispatch on types it's a sign that you should probably have started out with a variant type in the first place:
data StringOrInt = It'sAString String | It'sAnInt Int f :: StringOrInt -> String f (It'sAString _) = "string" f (It'sAnInt _) = "int"
...ideally with more descriptive, application-specific names.
That said, it is actually possible to have “dynamically typed” values in Haskell, like in Python. You just need to request the wrapper that contains the type information which the compiler would otherwise erase before the runtime:
{-# LANGUAGE TypeFamilies #-} import Data.Dynamic import Type.Reflection f :: Dynamic -> String f (Dynamic t _) = case eqTypeRep t (typeOf "string") of Just HRefl -> "string" _ -> "other"
Example usage:
main = do putStrLn . f $ toDyn "bla" putStrLn . f $ toDyn True putStrLn . f $ toDyn 'y'
yielding
string other other
f
比笨拙的eqTypeRep
构造更优雅的书写方式是
f :: Dynamic -> String f s = case fromDynamic s :: Maybe String of Just _ -> "string" _ -> "other"