2017-02-09 38 views
2

比方說,我們有:爲什麼haskell強制總是鍵入泛型?

data Data a b c = Build (a,b,c) deriving Show 

foo :: Data a b c -> Data a b c 
foo d = d 

main = print $ foo $ Build (1, 1, "a") 

有什麼辦法避免書面方式a b c每次使用的數據類型?

使用類型,是這樣的:

foo :: Data -> Data 
foo d = d 
+3

實際上你根本沒有寫*類型簽名。如果你忽略它們,Haskell會爲你派生它們。 –

+0

@WillemVanOnsem,我知道這件事,除此之外別說。將編輯 – Netwave

回答

11

是的,肯定的:

foo :: d ~ Data a b c => d -> d 
+1

好吧,類型的別名權? – Netwave

+0

@DanielSanchez不,這是[平等約束](https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/equality-constraints.html)。基本上它說'd'類型必須等於'Data a b c',但是你可以有更復雜的約束條件,比如'A a b c〜B d e f'。 Haskell * does *具有類型同義詞,但您必須使它們排名2,或添加參數。 – Bakuriu

+0

@DanielWagner,謝謝你使用這個 – Netwave

0

因爲Data不是一個類型,但類型構造。如果你喜歡一個函數,它需要3種類型並返回一個新類型。類型構造也可以種其他類型的構造函數作爲參數,例如

data D d a= D (d a a a) 

然後我就可以用你的Data(無參數)D Data a ......

8
data Data a b c = Build (a,b,c) deriving Show 
type D a t a' = Data a t a' 

foo :: D a t a' -> D a t a' 
foo d = d 

別名是有趣的,但是這不打算作爲一個嚴肅的答案。

編輯:嚴重的版本,如果你知道一個共同的單態類型,那麼別名成材:

type AppData = Data AppState AppValue AppResult 
foo :: AppData -> AppData 
... 
+0

優秀的答案。 –

+0

這是非常有創造力,偉大的工作! – AJFarmar

3

您可以在type代名詞包裹起來的多態類型。

{-# LANGUAGE RankNTypes #-} 
{-# LANGUAGE TypeOperators #-} 

type d ~> d' = forall a b c. d a b c -> d' a b c 

foo :: Data ~> Data 
foo d = d 

雖然寫出類型變量可能更簡單。

+0

我沒有完全理解這一點,你可以把我從網頁鏈接或東西請光?謝謝 – Netwave

+1

@DanielSanchez:簡而言之,當你在一個簽名中有類型變量時,它們隱式地具有*量詞*來定義它們的範圍,所以'foo :: Data a b c - > Data a b c'隱含地'全部a b c。數據a b c - >數據a b c'。 'Data〜> Data'類型擴展爲相同的東西,'全部a b c。數據a b c - >數據a b c',用'Data'替換'd'和'd''。 –

+0

@JonPurdy現在理解了,謝謝! – Netwave

相關問題