2014-12-02 25 views
0

我已經在過去一次寫入以下函數來將列表中的整數x的任何實例替換爲另一個整數y。這裏是我的代碼:如何更改此函數以使用任何類型,而不僅僅是Int

substitute::Int->Int->[Int]->[Int] 
substitute x y []   =[] 
substitute x y (z:zs) 
    |(z==x)     =y:substitute x y (zs) 
    |otherwise    =z:substitute x y (zs) 

下面是一個示例調用:

main = do 
print $ substitute 2 3 [2, 2, 2] 

我現在想與任何類型的輸入此代碼的工作。所以我嘗試將參數類型轉換爲通用的「a」,但是它會吐出一個錯誤,因爲Haskell認爲它是某種習慣的高階函數。那麼,如何使這項工作:找出

substitute::a->a->[a]->[a] 
substitute x y []   =[] 
substitute x y (z:zs) 
    |(z==x)     =y:substitute x y (zs) 
    |otherwise    =z:substitute x y (zs) 


main = do 
print $ substitute 2 'a' [2, 2, 2] 
+0

在您的下一個問題中,請始終發佈錯誤。它通常會幫助讀者,並提高你得到答案的機會。 – chi 2014-12-02 09:41:37

回答

2

的一種方法是從你的代碼中刪除類型簽名,發現它使用ghci的:

λ> :t substitute 
substitute :: Eq a => a -> a -> [a] -> [a] 

Haskell有一個很好的類型推斷,所以它會自動爲您提供最多樣化的類型。

substitute :: Eq a => a -> a -> [a] -> [a] 
substitute x y []   =[] 
substitute x y (z:zs) 
    |(z==x)     =y:substitute x y (zs) 
    |otherwise    =z:substitute x y (zs) 

UPDATE:剛纔看到你更新的問題。 Haskell在默認情況下沒有異構列表,所以你不想要做什麼。但是你可以使用Existential數據類型來獲得你想要的。閱讀this section瞭解更多關於它。

{-# LANGUAGE ExistentialQuantification #-} 

data ShowBox = forall s. Show s => SB s 

instance Show ShowBox where 
    show (SB s) = show s 

substitute :: ShowBox -> ShowBox -> [ShowBox] -> [ShowBox] 
substitute x y []   =[] 
substitute (SB x) (SB y) ((SB z):zs) 
    |(show z == show x) = (SB y):substitute (SB x) (SB y) (zs) 
    |otherwise    = (SB z):substitute (SB x) (SB y) (zs) 

λ> substitute (SB 'a') (SB 3) [SB 1, SB 'a', SB 3] 
[1,3,3] 

請注意,上述程序是反模式。除非你有正確的理由,否則不要這樣做。

+0

所以如何做這個編譯:main = do print $ substitute 2「a」[2,2,2] – 2014-12-02 06:15:19

+0

@KannyBros更新了我的答案。 – Sibi 2014-12-02 06:38:21

0

Haskell支持多態性,因此可以創建類似於您需要的函數。 @Sibi的迴應顯示了找出它的一種方法,但並不能解釋爲什麼,所以我會告訴你爲什麼。

很明顯,你的函數的類型爲a -> a -> [a] -> [a],如你所指出的,而是因爲你使用==功能,屬於Eq類型類,應用了約束:(Eq a) => a -> a -> [a] -> [a]。是的,這需要Haskell類型類的知識,但是當你沒有GHCi的時候值得學習。

有時我們可以通過使用模式匹配來避免在我們的函數類型中使用典型的Eq,但不幸的是,我沒有看到任何最新的方法來刪除==並替換模式。也許在未來,Haskell將支持像plus a a = 2 * a這樣的函數模式,但這是一廂情願的想法。

理解多態類型簽名的一個有用的註釋是類似上述a的名稱被稱爲類型變量。將它們與具體類型區分開的方式很簡單:它們始終以小寫字母開頭,而類型類構造函數以大寫字母或:開頭,用於中綴構造函數,但函數中綴構造函數->除外。

相關問題