是否可以在类型名称本身而不是在某个类型的构造函数上进行模式匹配?
这是一个人为的例子,代码没有编译,我希望能解释我之后的事情:
what :: a -> String
what (x :: String) = "It's a String!"
what (x :: Int) = "It's an Int!"
what x = "Not sure what it is."
答案 0 :(得分:6)
这是一个使用type-classes的版本:
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module Test where
class What a where
what :: a -> String
instance What String where
what _ = "It's a String!"
instance What Int where
what _ = "It's an Int"
示例:
λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
如果您想要 else 案例:
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverlappingInstances #-}
module Test where
class What a where
what :: a -> String
instance What String where
what _ = "It's a String!"
instance What Int where
what _ = "It's an Int"
instance What a where
what _ = "not sure"
示例:
λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what True
"not sure"
答案 1 :(得分:5)
请注意,您要求的是一些非惯用的东西。无论你真正想做什么,这可能都不是正确的做法!
您的顶级类型签名表示您可以处理任何类型的任何类型,而且不会飞。类型在编译时都会丢失,因此您需要一些东西来告知代码类型是什么,这是做出分支决策的。
你可以在这里使用一些较少使用的课程。一个叫做Typeable
,是一个具有运行时表示的类型的类:
class Typeable (a :: k) where
Data.Typeable.Internal.typeRep# :: GHC.Prim.Proxy# a -> TypeRep
为了在你的情况下使用typeable,你可以将约束添加到你的类型变量中,并使用typeOf
来获取类型表示:
{-# LANGUAGE MultiWayIf #-}
import Data.Typeable
what :: Typeable a => a -> String
what x =
let ty = typeOf x
in if | ty == intTy -> "It's an Int!"
| ty == strTy -> "It's a String!"
| otherwise -> "Something else, namely: " ++ show ty
where
strTy = typeOf ""
intTy = typeOf (0 :: Int)
让步操作:
*Main> what (1::Int)
"It's an Int!"
*Main> what "foo"
"It's a String!"
*Main> what 1.1
"Something else, namely: Double"
答案 2 :(得分:4)
不,那是不可能的。
根据类型执行不同操作的唯一方法是使用对每种类型实现不同的类型类方法。
答案 3 :(得分:3)
在某种程度上,你试图在Haskell中重载一个函数。看一下这篇解释涉及类型类的方法的帖子:Overloading function signatures haskell