2012-09-14 32 views
3

一個簡短的搜索並沒有幫助我找到答案,所以我開始懷疑它的存在。該追問很簡單:我想創建一個多態函數,像這樣:在Haskell中創建多態函數

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

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

針對不同類型有不同的定義函數的意思。這是可能的,以及如何?

+2

你的第一個'F'沒有正確的類型。 –

+0

另請參閱http://stackoverflow.com/questions/5671303/what-is-haskells-style-of-polymorphism –

+0

@DonStewart:謝謝,這是一個錯字。 – aplavin

回答

13

有多態性的兩種風格在Haskell:

  • parameteric多態性;和
  • 界定多態性

首先是最一般的 - 的功能是多態的參數化,如果它均勻地表現爲所有類型的,在它的類型參數中的至少一個。

例如,函數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) 
+0

而'funnyshow'只是一個常規函數,或者在使用它時有一些特定的事情需要記住? – aplavin

+1

這是一個常規功能。如果您嘗試在沒有實例的類型上使用它,則會出現編譯錯誤。 –

+0

謝謝,這似乎是正確的解決方案。然而,奇怪的是,我沒有注意到在我看過的幾個haskell程序中使用'instance'。 – aplavin

6

以下是如何使用類型族實現類似的功能。

那麼,如果你有相同的返回類型,那麼你可以在不使用類型族的情況下實現行爲,並且只使用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 

在ghci中

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

*Main> f "Hello" 
"5" 

*Main> f (2::Float) 
2.0 
+2

類型家庭很漂亮。 –

+0

'length'如何返回一個'String'? :) – is7s

+0

@ is7s對不起,我沒有完全改變它後,作者修改了這個問題..謝謝..更正.. – Satvik