![](/img/trans.png)
[英]Why type constructors can not be used in typeclass definition in haskell?
[英]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
。
如果您嘗試存儲任何類似的函數,只要m
是Monad
,請將其用作類型參數,並在函數中指定此約束:
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.