2014-04-14 39 views
10

我一直在研究這個article中給出的用於創建鏡頭的示例。鏡頭和單態限制

我創建Lens在文章中指出和下面是我的代碼:

{-# LANGUAGE TemplateHaskell #-} 
import Control.Lens 

type Degrees = Double 
type Latitude = Degrees 
type Longitude = Degrees 

data Meetup = Meetup { _name :: String, _location :: (Latitude, Longitude) } 
makeLenses ''Meetup 

meetupLat = location._1 :: Lens' Meetup Latitude 

現在這個代碼不進行類型檢查,除非我有這樣的:

{-# LANGUAGE NoMonomorphismRestriction #-} 

但沒有在那裏的文章,我可以發現他們提到了關於單態限制的 。所以這是一個正常的事情,或者我在這裏做錯了嗎?

編譯器使用:GHC 7.6.2

+0

如果將其定義爲'meetupLat :: Lens'Meetup Latitude',該怎麼辦? 'meetupLat = location._1'? – bheklilr

+0

@bheklilr謝謝,沒有擴展名的作品。你可以把它作爲答案嗎? – Sibi

+0

@bheklilr完成。 :) – Sibi

回答

11

這是正常的事情。該庫在很大程度上依賴於多態性,所以單態限制(使得事物的多態性比它們可能更小)不與其交互。在你的情況,我想你也可以寫你這樣的代碼:

meetupLat :: Lens' Meetup Latitude 
meetupLat = location._1 

如果你提供了一個綁定的顯性多態類型簽名時,單態限制並不重要。

請注意,Lens' Meetup Latitude多態性類型,即使它看起來是單形的。類型變量隱藏在Lens'類型同義詞的內部。特別是:

Lens' Meetup Latitudedefined作爲Lens Meetup Meetup Latitude Latitude

而且Lens Meetup Meetup Latitude Latitudedefinedforall f. Functor f => (Meetup -> f Meetup) -> Latitude -> f Latitude

因此,這是所有關於f。我認爲單態限制會強制f的具體實例化,但是您想保持它的多態性,因爲鏡頭的不同用戶會選擇不同的f。例如view將選擇Constset將選擇Identity。所以保持f多態性以允許鏡頭的用戶進行這些選擇是非常重要的。

4

你只需要指定的功能,而不是在其定義的類型

meetupLat :: Lens' Meetup Latitude 
meetupLat = latitude._1 

我相信這是因爲背後有複雜類型的Lens'的場景意味着儘管其定義具有該類型,但編譯器仍然難以猜測meetupLat具有相同的類型。也許有更深層次的單形態限制知識的人可以更好地闡述。