簡體   English   中英

可以在newtype定義中使用類型類約束嗎?

[英]Can a typeclass constraint be used in a newtype definition?

假設我們有以下newtype定義:

newtype A = A { _run :: Monad m => A -> [Int] -> m Int }

這不能用GHC 8.0.2編譯:

error: Not in scope: type variable ‘m’

正如我所料,用IO[]這樣的具體類型類替換m確實可以編譯。 鑒於這沒關系,為什么GHC不允許上面的簽名? 在這個newtype添加類型類約束有什么問題?

這取決於你想要存儲在A

如果您嘗試存儲任何類似的函數,只要mMonad ,請將其用作類型參數,並在函數中指定此約束:

newtype A m = A { _run :: A m -> [Int] -> m Int }

myFunction :: Monad m => A m -> A m

然后你可以在構造函數中包含A [] -> [Int] -> [Int]A Maybe -> [Int] -> Maybe Int

f :: A Maybe -> [Int] -> Maybe Int
f _ (x:_) = Just x
f _ [] = Nothing

g :: Monad m => A m -> [Int] -> m Int
g _ xs = return $ head xs

myA :: A Maybe
myA = A f  -- this works

myOtherA :: Monad m => A m
myOtherA = A g  -- this works too

另一方面,如果要強制存儲的數據是多態的,可以使用GHC擴展名RankNTypes

{-# LANGUAGE RankNTypes #-}
newtype A = A { _run :: forall m. Monad m => A -> [Int] -> m Int }

myFunction :: A -> A

你不能在構造函數中擁有類似A -> [Int] -> [Int]A -> [Int] -> Maybe Int的東西,因為forall強制它們在任何 Monad m上都是通用的,所以它會有成為Monad m => A -> [Int] -> Maybe Int

f :: A -> [Int] -> Maybe Int
f _ (x:_) = Just x
f _ [] = Nothing

g :: Monad m => A -> [Int] -> m Int
g _ xs = return $ head xs

myA :: A
myA = A f  -- this does not work ; it wants forall m. Monad m => m, not []

myOtherA :: A
myOtherA = A g  -- this does work

如果您打算為A值使用不同的特定Monad實例,這將非常有用。 例如,鏡頭以這種方式工作,使用不同的仿函數來對鏡頭做不同的事情。

這個有可能:

{-# LANGUAGE RankNTypes #-}
newtype A = A { _run :: forall m. Monad m => A -> [Int] -> m Int }

很難說出你想做什么,但這不是很有用。 任何A類值都需要適用於所有monad(您無法選擇)。

這也是可能的,具有相同的限制:

{-# LANGUAGE GADTs #-}
data A where A :: Monad m => (A -> [Int] -> m Int) -> A

但也許你的意思更像

newtype A m = A { _run :: A m -> [Int] -> m Int }

這允許使用不同monad的不同類型的A值。

當您創建A類型的數據時,GHC將如何知道Monad哪個實例?

或者,換句話說,類型變量m不在類型定義左側的范圍內。 這意味着它不知道m應該是什么,也無法解決。 這是隱含的。

我確信你可以通過某種方式使用擴展來做你想做的事情。 (RankNTypes擴展名),但是我們需要知道你的更多內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM