在Haskell中创建多态函数

apl*_*vin 8 polymorphism haskell function

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

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

f :: Int -> String
f i = show i
Run Code Online (Sandbox Code Playgroud)

为不同类型定义的函数是不同的.有可能,怎么样?

Don*_*art 17

Haskell中有两种类型的多态性:

  • 参数多态性; 和
  • 有界多态性

第一个是最通用的 - 如果函数在至少一个类型参数中对所有类型均匀地表现,则该函数是参数化多态的.

例如,函数length是多态的 - 它返回列表的长度,无论列表中存储的是什么类型.

length :: [a] -> Int
Run Code Online (Sandbox Code Playgroud)

多态性由小写类型变量指示.

现在,如果你有,你希望有一定的自定义行为设置的类型,那么你已经为界多态性(也被称为"特设").在Haskell中,我们使用类型类.

该类声明哪些函数可用于一组类型:

class FunnyShow a where
    funnyshow :: a -> String
Run Code Online (Sandbox Code Playgroud)

然后您可以为您关心的每种类型定义实例:

instance FunnyShow Int where
    funnyshow i = show (i+1)
Run Code Online (Sandbox Code Playgroud)

有可能:

instance FunnyShow [Char] where
   funnyshow s = show (show s)
Run Code Online (Sandbox Code Playgroud)

  • @chersanya:你用过'show`吗?``== /`/ =`?`<`/`<=`/`>`/`> =`?或者`+`/`-` /`*`?这些是Prelude中类型类的所有(部分)函数:[`Show`](http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t: Show),[`Eq`](http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Eq),[`Ord`](http:// www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Ord)和[`Num`](http://www.haskell.org/ghc/docs/latest/ html/libraries/base/Prelude.html #t:Num).所以你没有看到很多`实例,因为大部分内容已经为你完成了. (2认同)
  • @chersanya:这并不令人惊讶。某些类型的实例只需要声明一次即可在任何地方使用,并且大多数标准类型都已经声明了标准实例。与普通程序相比,这更像是您希望在定义新类型的库中看到的代码类型。此外,诸如“Show”和“Eq”之类的常见类可以使用“deriving”来指定,编译器会在其中为您编写实例,因此,如果您见过“deriving (Show, Eq)”之类的内容,那么您就已经看到了声明实例的不同方式。 (2认同)

Sat*_*vik 12

以下是使用类型系列实现类似功能的方法.

好吧,如果你有相同的返回类型,那么你可以实现行为而不使用类型系列,只使用Don建议的类型类.

但是当你想支持更复杂的adhoc多态时,最好使用类型族,比如每个实例的不同返回类型.

{-# 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  
Run Code Online (Sandbox Code Playgroud)

在ghci

*Main> f (2::Int)
"2"

*Main> f "Hello"
"5"

*Main> f (2::Float)
2.0
Run Code Online (Sandbox Code Playgroud)

  • 类型家庭很漂亮. (3认同)