Haskell如何处理重载多态?

Sud*_*ha 17 polymorphism haskell

我有一个关于Haskell多态性的问题.

据我所知,有两种类型的多态性:

  1. 参数:您没有指定输入类型.

    例:

    functionName :: [a] -> a
    
    Run Code Online (Sandbox Code Playgroud)
  2. 重载:作为命令式编程,即将不同的参数传递给同一个函数.

我的问题是:Haskell如何处理重载

ham*_*mar 44

Haskell中的重载是使用类型类完成的.例如,假设您要重载一个foo返回以下内容的函数Int:

class Fooable a where
    foo :: a -> Int

instance Fooable Int where
    foo = id

instance Fooable Bool where
    foo _ = 42
Run Code Online (Sandbox Code Playgroud)

但是,它们比大多数语言中的重载机制更强大.例如,您可以在返回类型上重载:

class Barable a where
    bar :: Int -> a

instance Barable Int where
    bar x = x + 3

instance Barable Bool where
    bar x = x < 10
Run Code Online (Sandbox Code Playgroud)

有关更多示例,请查看Haskell 中的预定义类型类.


And*_*ewC 6

在某些语言中,重载意味着对于提供类似但不同功能的多个函数使用相同的名称,因此您可以尝试

split :: String -> [String]                      -- splits on whitespace
split :: Char -> String -> [String]              -- splits on the given character
split :: [Char] -> String -> [String]            -- splits on any of the given characters
split :: (Char -> Bool) -> String -> [String]    -- splits using a function that tells you when
Run Code Online (Sandbox Code Playgroud)

这会给你带来的Duplicate type signature错误.

Haskell不会进行这种类型的重载,而Haskell程序员会给出这些不同的名称:

words :: String -> [String]                        -- splits on whitespace
splitOn :: Char -> String -> [String]              -- splits on the given character
splitsOn :: [Char] -> String -> [String]           -- splits on any of the given characters
splitWith :: (Char -> Bool) -> String -> [String]  -- splits using a function that tells you when
Run Code Online (Sandbox Code Playgroud)

Haskell不允许我认为你要问的那种超载的原因是,它真的不会让你做任何你没有做过的事情,并允许它几乎不可能做到这一点更高级的重载.Haskell的重载确实是一个非常强大的工具; 了解类型类和构造函数类以开始.

实际上,由于String= [Char]和Haskell程序员喜欢代码重用,他们更有可能写:

words :: String -> [String]                -- splits on whitespace
splitOn :: Eq a => a -> [a] -> [[a]]       -- splits on the given item
splitsOn :: Eq a => [a] -> [a] -> [[a]]    -- splits on any of the given items
splitWith :: (a -> Bool) -> [a] -> [[a]]   -- splits using a function that tells you when
Run Code Online (Sandbox Code Playgroud)

下面Eq a是Haskell允许的一种重载的示例,splitOn只要可以比较项目的相等性,就可以分割任何列表(即Haskell允许您定义自己的相等概念).您可以使用它来分割字符串,或者例如字符串列表,但是您不能拆分函数列表,因为您无法检查两个函数以查看它们是否相等.splitWith是一个Haskell的例子,让你像处理大多数其他数据一样处理函数 - 你可以传递一个作为参数!

[注1:words是一个标准函数,splitWith在一个具有略微不同类型签名的库中.]
[注2:如果你想实际编写这些函数,请按以下方式:

splitWith isSplitter list =  case dropWhile isSplitter list of
  [] -> []
  thisbit -> firstchunk : splitWith isSplitter therest
    where (firstchunk, therest) = break isSplitter thisbit

-- words = splitWith isSpace           -- not needed, standard function from the Prelude
splitOn c = splitWith (== c)           -- notice I passed == in an argument! 
splitsOn chars = splitWith (`elem` chars)
Run Code Online (Sandbox Code Playgroud)

]