[英]Why can't a function take a type constrained only by a typeclass?
我沒有足夠的詞匯來表達這個問題(因此,為了尋找答案,如果答案很容易獲得,那么道歉)。 考慮以下
class RunFoo m where
runFoo :: m a -> a
class RunFooWrapper m where
doRunFoo :: (RunFoo n) => n a -> m a
newtype RunFast a = RunFast a
newtype RunSlow a = RunSlow a
fooExample :: (RunFoo m) => m Bool
fooExample = undefined
fooWrapperExample :: (RunFooWrapper m) => m Bool
fooWrapperExample = doRunFoo fooExample
這不編譯: Could not deduce (RunFoo n0) arising from a use of 'doRunFoo'
。
似乎編譯器(GHC 7.10)堅持從fooExample
具體實例化m
,因此拒絕繼續。 但在這種情況下,我無法fooExample
為什么程序是錯誤類型的 - fooExample
顯式定義了RunFoo m
,所有doRunFoo
需要的是RunFoo x
。 那么為什么這不起作用呢?
作為一個補充問題,是否存在某種特殊的擴展(可能與存在類型有關),允許這樣的程序? 理想情況下,我希望能夠說doRunFoo采用存在的任何定義(?)作為RunFoo m => m
(而不是采用任何具體的RunFoo
實例)。
動機
我想創建可組合函數,這些函數在類型類約束的類型的某些方面運行 - 我可以提供一個具體的例子,說明我的意思,如果有必要的話!
編輯更多的動力和替代實施
我對一般情況下這個問題的答案感到好奇,但我想我會在上下文中添加一些我遇到的問題,我真正想要的是monad之間的一種約束委托。 所以我想在一個monad中編寫函數,只能通過在另一個類型類中調用monad的類型類來約束。 然后可以在不同的上下文中運行頂級函數,執行相同的邏輯,但根據包裝monad將底層實現換出。 由於包裝和實現monad之間存在一對一的對應關系,我可以使用類型系列來實現這一點,所以
class (RunFoo (RunFooM m)) => RunFooWrapper m where
type RunFooM m :: * -> *
doRunFoo :: RunFooM m a -> m a
instance RunFooWrapper RunFooWrapperSlow where
type RunFooM RunFooWrapperSlow = RunSlow
doRunFoo :: [...]
這意味着fooExample
m
的分辨率由包裝器monad的類上下文決定,並且似乎工作正常,但與haoformayor提供的解決方案相比,它是一個非常狹窄的解決方案。
{-# language RankNTypes #-}
class RunFoo m where
runFoo :: m a -> a
class RunFooWrapper m where
doRunFoo :: (forall n. RunFoo n => n a) -> m a
fooExample :: RunFoo m => m Bool
fooExample = undefined
fooWrapperExample :: RunFooWrapper m => m Bool
fooWrapperExample = doRunFoo fooExample
(forall n. RunFoo n => na) -> ma
是關鍵區別。 它允許您傳入fooExample
,其類型為forall m. RunFoo m => m Bool
forall m. RunFoo m => m Bool
(編譯器隱式添加了forall
),因此m
與n
結合,每個人都很高興。 雖然我無法讀懂思想,但我相信這種類型反映了你的真實意圖。 您只需要一個RunFoo
實例,僅此而已將n
作用於第一個參數提供它。
問題是你的代碼被隱式輸入為forall n. RunFoo n => na -> ma
forall n. RunFoo n => na -> ma
。 這意味着你需要首先選擇一個n
,使得RunFoo n
然后提出一個類型為na
的值作為第一個參數傳入。 移動括號的這種簡單行為(增加n
的等級)完全改變了含義。
有關具有相同問題的人的示例,請參閱此Stack Overflow問題 。 有關RankNTypes
的更好解釋,請參閱Oliver的博客文章 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.