简体   繁体   English

在Haskell中创建多态函数

[英]Creating polymorphic functions in Haskell

A short search didn't help me to find the answer, so I started to doubt in its existance. 一个简短的搜索并没有帮助我找到答案,所以我开始怀疑它的存在。 The question is simple. 问题很简单。 I want to create a polymorphic function, something like this: 我想创建一个多态函数,如下所示:

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

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

A function defined differently for different data types is meant. 为不同数据类型定义的函数是不同的。 Is it possible? 可能吗? If yes, how? 如果有,怎么样?

There are two flavors of polymorphism in Haskell: Haskell中有两种类型的多态性:

  • parameteric polymorphism; 参数多态性; and
  • bounded polymorphism 有界多态性

The first is the most general -- a function is parametrically polymorphic if it behaves uniformly for all types, in at least one of its type parameters. 第一个是最通用的 - 如果函数在至少一个类型参数中对所有类型均匀地表现,则该函数是参数化多态的。

For example, the function length is polymorphic -- it returns the length of a list, no matter what type is stored in its list. 例如,函数length是多态的 - 它返回列表的长度,无论列表中存储什么类型。

length :: [a] -> Int

The polymorphism is indicated by a lower case type variable. 多态性由小写类型变量指示。

Now, if you have custom behavior that you want to have for a certain set of types, then you have bounded polymorphism (also known as "ad hoc"). 现在,如果你有,你想为一特定的类型的自定义行为,那么你已经为界多态性(也被称为“特设”)。 In Haskell we use type classes for this. 在Haskell中,我们使用类型类。

The class declares which function will be available across a set of types: 该类声明哪些函数可用于一组类型:

class FunnyShow a where
    funnyshow :: a -> String

and then you can define instances for each type you care about: 然后您可以为您关心的每种类型定义实例:

instance FunnyShow Int where
    funnyshow i = show (i+1)

and maybe: 有可能:

instance FunnyShow [Char] where
   funnyshow s = show (show s)

Here is how you can achieve something similar using type families. 以下是使用类型系列实现类似功能的方法。

Well if you have same return types then you can achieve the behaviour without using type families and just using type classes alone as suggested by Don. 好吧,如果你有相同的返回类型,那么你可以实现行为而不使用类型系列,只使用Don建议的类型类。

But it is better to use type families when you want to support more complex adhoc polymorphism, like different return types for each instance. 但是当你想支持更复杂的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  

In ghci 在ghci

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

*Main> f "Hello"
"5"

*Main> f (2::Float)
2.0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM