简短的搜索并没有帮助我找到答案,所以我开始怀疑它的存在。问题很简单。我想创建一个多态函数,如下所示:
f :: String -> String
f s = show (length s)
f :: Int -> String
f i = show i
意味着针对不同数据类型定义不同的函数。可能吗?如果是,如何?
简短的搜索并没有帮助我找到答案,所以我开始怀疑它的存在。问题很简单。我想创建一个多态函数,如下所示:
f :: String -> String
f s = show (length s)
f :: Int -> String
f i = show i
意味着针对不同数据类型定义不同的函数。可能吗?如果是,如何?
Haskell 中有两种多态性:
第一个是最通用的——一个函数是参数多态的,如果它对所有类型的行为一致,至少在它的一个类型参数中。
例如,该函数length
是多态的——它返回一个列表的长度,不管它的列表中存储的是什么类型。
length :: [a] -> Int
多态性由小写类型变量指示。
现在,如果您希望对特定类型集具有自定义行为,那么您就有了有界多态性(也称为“ad hoc”)。在 Haskell 中,我们为此使用类型类。
该类声明了哪些函数将在一组类型中可用:
class FunnyShow a where
funnyshow :: a -> String
然后您可以为您关心的每种类型定义实例:
instance FunnyShow Int where
funnyshow i = show (i+1)
有可能:
instance FunnyShow [Char] where
funnyshow s = show (show s)
以下是使用类型族实现类似功能的方法。
好吧,如果您具有相同的返回类型,那么您可以在不使用类型系列的情况下实现该行为,而只需按照 Don 的建议仅使用类型类。
但是当您想要支持更复杂的即席多态性时,最好使用类型族,例如每个实例的不同返回类型。
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
class F a where
type Out a :: *
f :: a -> Out a
instance F String where
type Out String = String
f = show . length
instance F Int where
type Out Int = String
f = show
instance F Float where
type Out Float = Float
f = id
在 ghci
*Main> f (2::Int)
"2"
*Main> f "Hello"
"5"
*Main> f (2::Float)
2.0