2016-01-09 76 views
2
import Data.Monoid 

newtype Constant a b = 
    Constant { getConstant :: a } 
    deriving (Eq, Ord, Show) 

instance Functor (Constant a) where 
    fmap _ (Constant a) = Constant a 

instance (Monoid a) => Applicative (Constant a) where 
    pure x = Constant (mempty x) 
    _ <*> (Constant a) = Constant a 

--:t (<*>) 
--(<*>) :: Applicative f => f (a -> b) -> f a -> f b 

--:t Constant (Sum 1) 
--Constant (Sum 1) :: Num a => Constant (Sum a) b 

--Constant (Sum 1) <*> Constant (Sum 2) 
--Constant { getConstant = Sum { getSum = 2 }} 

我的問題是爲什麼最後一個語句類型檢查?Haskell爲什麼這種類型檢查

我預期的< *>左側爲類型F的(A - > B)

F =常數
(一 - > B)= 1總和?

沒有什麼我可以適用的(總和1),因爲它被完全應用,但這個語句編譯。

+0

在你的定義'mempty x'的作品,雖然mempty'的'類型'是一個含半幺羣=>了' 。嘗試用'pure x = Constant(mempty x x x x x x 127「abc」()x x)'替換此定義。它工作嗎?爲什麼? ;) –

回答

3

因爲你有兩個類型變量在這裏:

newtype Constant a b = 
    Constant { getConstant :: a } 
    deriving (Eq, Ord, Show) 

但是你第一類唯一的「商店」的價值觀,第二個是phantom

但你Applicative實例只關心你有類型的變量 - 在b,難以捉摸的幻象。

這意味着像Constant (Sum 1)這樣的值可以具有任何類型的東西作爲它們的第二個類型變量 - 沒關係!你可以這樣寫:

foo :: Constant Sum (a -> b) 
foo = Constant (Sum 1) 

bar :: Constant Sum String 
bar = Constant (Sum 1) 

baz :: Constant Sum (IO [Maybe Int]) 
baz = Constant (Sum 1) 

因爲你從來不需要幻影類型的值。

因此,當你寫Constant (Sum 1) <*> Constant (Sum 2),類型檢查推斷正確的類型:

let foo = Constant (Sum 1) :: Constant Sum (a -> b) 
    bar = Constant (Sum 2) :: Constant Sum a 
in foo <*> bar 

所以<*>的左側確實有型f (a -> b),但fConstant Sum,不只是Constant

+0

所有優秀的答案,我選擇這個,因爲「f是恆定」把釘子釘在棺材裏給我。謝謝。 – mac10688

4

左側f (a -> b)。這是對的。

記住這裏的類型(讓我們1 :: Int爲簡單起見):

Constant (Sum 1) :: forall a. Constant (Sum Int) a 

我已經添加了明確forall。類型檢查器可以統一a與任何東西。

試試這個:

Constant (Sum 1) :: Constant (Sum Int) (a -> b) 

工作正常。

4

對於Const

(<*>) :: Const c (a -> b) -> Const c a -> Const c b 

你的輸入是一個Const c (a -> b)一個Const c a。你給出Const c b作爲回報 - 如果是x :: c,則Const x :: Const c a,對於任何a。它可以是Const c Int,Const c Bool等。

例如:

Const "Hello" :: Const String Int 
Const "Hello" :: Const String Bool 
Const "Hello" :: Const String Double 
Const "Hello" :: Const String a 
Const "Hello" :: Const String (a -> b) 
Const "Hello" :: Const String b 

所有類型檢測,因爲最後一個參數可以是任何東西 - "Hello"不僅制約了第一個參數。

但是,您應該注意,您的Applicative實例不服從適用法律。

u <*> pure y = pure ($ y) <*> u 
特別

受到侵犯:

Const "hello" <*> pure 4 
== Const "hello" <*> Const "" 
== Const "" 

pure ($ 4) <*> Const "hello" 
== Const "" <*> Const "hello" 
== Const "hello" 
+1

適用法律的好處。 –

+0

似乎常數固有地破壞了應用法則。 – mac10688

+2

@ mac10688不太夠;有可能爲'Constant'編寫合法的應用實例:) –