[英]How can I prove to GHC that (b ~ Foo)?
我不會假裝我知道如何思考或談論哈斯克爾。 在偽java-oo-jargon中:
我想要做的是有一個“實現”“接口”的“結構”。 該接口的一部分是一個返回實現另一個接口的對象的函數。
interface IFiz {}
interface IBuz {
function IFiz getFiz()
}
class Foo implements IFiz { ... }
class Bar implements IBuz {
IFiz fiz = new Foo();
function getFiz() {
return fiz;
}
}
我怎么能在Haskell中做到這一點? 我這樣做的嘗試如下所述。
我怎樣才能向GHC證明(b~Foo)?
我對這個問題的理解:
Foo是類型類Fiz的一個實例。
我希望Bar成為類型Buz的一個實例。
但是,編譯器無法在punk
方法的實現中推斷出(b~Foo)。 但還有什么呢? 我嘗試使用不推薦的直接方式添加數據約束,以及使用GADT,但似乎都沒有工作(我繼續得到完全相同的錯誤。)
data Foo = Foo Int
data Bar = Bar Foo
class Fiz a where
funk :: a -> a -- Not important, I just wanted to put something in Fiz
class Buz a where
punk :: Fiz b => a -> b
instance Fiz Foo where
funk a = a
instance Buz Bar where
punk (Bar foo) = foo
Could not deduce (b ~ Foo)
from the context (Fiz b)
bound by the type signature for punk :: Fiz b => Bar -> b
at Test.hs:42:5-8
‘b’ is a rigid type variable bound by
the type signature for punk :: Fiz b => Bar -> b at Test.hs:42:5
Relevant bindings include punk :: Bar -> b (bound at Test.hs:42:5)
In the expression: foo
In an equation for ‘punk’: punk (Bar foo) = foo
此類型簽名:
class Buz a where
punk :: Fiz b => a -> b
說punk
必須能夠為任何類型b
返回類型b
東西,因為它是Fiz
實例。 所以問題不在於編譯器不能推斷出Foo
是Fiz
實例,而是返回值不是Quux
,這是Fiz
一個實例。
data Quux = Quux
instance Fiz Quux where
funk a = a
如果你想讓函數類型返回任何Fiz
實例,你可以使用ExistentionalQuantification擴展:
{-# LANGUAGE RankNTypes, ExistentialQuantification #-}
data Foo = Foo Int
data Bar = Bar Foo
data SomeFiz = forall a . Fiz a => SomeFiz a
class Fiz a where
funk :: a -> a
class Buz a where
punk :: a -> SomeFiz
instance Fiz Foo where
funk a = a
instance Buz Bar where
punk (Bar foo) = SomeFiz foo
否則,如果你真的想要實現這個類型類,你只能通過將底部傳遞給funk
:
instance Buz Bar where
punk _ = funk undefined
-- or for example:
instance Buz Bar where
punk _ = funk (funk undefined)
或者通過修復funk:
instance Buz Bar where
punk _ = fix funk
如果你能提供你想要達到的目標的更多細節,也許我會給出更多有用的答案。
你不能。
Buz
類說如果a
有一個Buz
實例,那么對於每個有一個Fiz
實例的b
,你可以從a -> b
提供一個函數。 Fiz
在制作b
幾乎沒有任何幫助; funk
只會給你一個b
,如果你已經有了一個b
。
您可能誤解了GHC的錯誤消息。 類型推斷是雙向的。 在這種情況下, b
來自Buz
類中的punk
簽名。 它要求的結果punk
是類型的東西b
每種類型b
。 Foo
不是所有類型的東西。
‘b’ is a rigid type variable bound by
the type signature for punk :: Fiz b => Bar -> b at Test.hs:42:5
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.