2015-08-14 48 views
1

我不太確定爲什麼兩個中間表達式沒有鍵入check。類型檢查器似乎爲每個發生的m刷新了新的綁定。是否有擴展名允許在所有這些位置重用名稱m在haskell中的表達式中鍵入類和綁定重用

test :: MonadPlus m => m a 
test = 
    let r = mzero :: m a -- fails 
    in let r' :: m a = mzero -- fails 
     in mzero 
+2

[ScopedTypeVariables](https://wiki.haskell.org/Scoped_type_variables)但在這種情況下,您不使用'r'和'r'',所以我沒有看到您的觀點 - 也許您可以找到一個更好的例子? – Carsten

+0

我想遞增地寫表達式,在各個地方首先使用undefined。這就是爲什麼我想要約束的類型 – nicolas

回答

3
{-# LANGUAGE ScopedTypeVariables #-} 
{-# LANGUAGE UnicodeSyntax  #-} 

test :: ∀ m a . MonadPlus m => m a 
test = 
    let r = mzero :: m a 
    in let r' :: m a = mzero 
     in mzero 

如果你不喜歡在你的代碼的非ASCII字符,您也可以省略-XUnicodeSyntax和代替和FORALL使用forall關鍵字;.

什麼這個關鍵字的作用是,

  1. 它引入了新的類型變量ma,如普遍量化。現在,通常Haskell只是假設任何類型的變量在同一個(!)簽名中還沒有被提及是普遍的。但是
  2. 它禁止在整個上下文範圍內自動引入類型變量。這也包括r = mzero :: m a,所以在這一點上GHC知道這是不是應該引進ma爲新變量,但重複使用相同的ma如在test簽名。
+0

將upvote,如果你解釋什麼forall關鍵字/符號在這裏做。 – Jolta

+1

'forall a .'就像是'\ a - >'的類型。通常當你寫一個簽名像'f :: a - > [a]''a'從哪裏來?我們認識到它的含義是「一些未知的類型變量」,但是這是通過編寫'f :: forall a'來形式化的。 a - > [a]'。事實上,Haskell自動將事情解決。 –