[英]Function application as identiity Monad: how is it an instance of the Monad typeclass?
[英]How to define a Monad instance “m a” with “a” in Typeclass Show?
我想用容器 M 定義一個 monad 實例作為 monad 並且包含的類型a
應該是 class Show
的成員。 類型系統應確保此約束(即a
是Show
的成員)。
我像這樣嘗試過,但不幸的是M
不是正確的類型:
data M = forall a. Show a => M a
instance Monad M where
return x = M x
實現這一目標的所有其他嘗試都會遇到以下問題:由於Monad
是構造函數 class,我沒有顯式訪問所包含元素的a
類型,因此我無法限制它。
有沒有人知道這個沒有定義新的Monad
class 的解決方案?
嗯,實際上可以在某種意義上限制類型構造函數的參數,使用 GADT:
data M a where
M :: (Show a) => a -> M a
不幸的是,這實際上對您沒有幫助。 在某種程度上,它實際上使事情變得更糟,因為沒有約束的Monad
實例,根本不可能編寫實例。
如果您查看上面的構造函數類型簽名,它顯然類似於return
——這說明了為什么您正在做的事情根本上是不可能的。 返回的類型是: (Monad m) => a -> ma
,並且像往常一樣,未綁定的類型變量在最外層被隱式地普遍量化,因此您可以將其讀作“對於所有可能的類型a
和所有可能的類型m
這是Monad
的實例,給定 a 類型a
值,您可以構造ma
類型的值。 這里的“for all”措辭非常直白—— return 的類型不僅僅是使用類型變量,它還積極地斷言必須允許任何類型a
。
所以,簡而言之,沒有。 沒有辦法做你想做的事,因為標准Monad
class明確指定了相反的內容。
您可能無法完全按照您的要求進行操作,但另一種可能性是您的特定 monad 提供一個動作,該動作明確地執行您想要使用Show
執行的任何操作。 也就是說,假設您有:
data M a = {- ... -}
instance Monad M where -- notice: no Show constraint
{- ... -}
然后您可以另外提供一些操作:
report :: Show a => M a -> M a
我想不出用Show
很好地使用這種模式,但我知道一個類似的例子,你可能希望使用Ord
約束。 設置是您想要創建一個不確定的 monad(如[a]
),但沒有重復項(如Set a
)。 刪除重復項需要一些上下文,例如Eq
或Ord
,但我們不能在每次return
/ >>=
操作時都要求這樣做。 因此,我們要求用戶明確標記應合並重復項的點:
newtype Setlike a = Setlike { toList :: [a] }
instance Monad Setlike where
return x = Setlike [x]
Setlike xs >>= f = [y | x <- xs, let Setlike ys = f x, y <- ys]
collapse :: Ord a => Setlike a -> Setlike a
collapse = Setlike . Data.Set.toList . Data.Set.fromList . toList
這可以像這樣使用:
valuesOfInterest = collapse $ do
v1 <- allValues
v2 <- allValues
doSomethingInteresting v1 v2
然后,即使v1
和v2
的某些配對碰巧產生相同的感興趣值,該值也只會在結果中出現一次。
您的用例也可能有一些類似的技巧。
不,這是不可能的,盡管很容易解釋。 看看return
的類型簽名:
return :: Monad m => a -> m a
簽名不能改變,所以你的 monad 必須接受任何內容類型。 由於類型 class 本身沒有提及內容類型,因此無法對其強制執行約束。
您可以做的一件事是在所有需要它的函數上編寫此約束並刪除全局限制。 如果您可以僅在需要時證明Show
約束的存在,系統的健全性仍然得到保證。
這可以通過一些極端的技巧來實現。 有關實現,請參見rmonad package。 但是,這可能不值得。
為什么你需要有a
is Show
的約束? 在那個時候強制執行 Show 約束會更容易,然后它會在必要時自然傳播。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.