10

简短的搜索并没有帮助我找到答案,所以我开始怀疑它的存在。问题很简单。我想创建一个多态函数,如下所示:

f :: String -> String
f s = show (length s)

f :: Int -> String
f i = show i

意味着针对不同数据类型定义不同的函数。可能吗?如果是,如何?

4

2 回答 2

22

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)
于 2012-09-14T19:21:11.990 回答
14

以下是使用类型族实现类似功能的方法。

好吧,如果您具有相同的返回类型,那么您可以在不使用类型系列的情况下实现该行为,而只需按照 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
于 2012-09-14T19:27:29.333 回答