我正在從事一個數學專案,一直需要從型別中提取規范的“基礎”,因此我定義了以下型別類。
class Basis a where
getBasis :: Int -> [a]
我想在一個單獨的函式中使用這個基礎:
foo :: (Basis a) => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis n
undefined
-- Do some stuff with the basis using the function f.
-- theBasis should have type [a].
但是,這無法進行型別檢查,從而產生表單錯誤Could not deduce (Basis a0) arising from the use of 'getBasis' from the context: Basis a。
我試圖通過顯式撰寫預期型別來幫助型別檢查器:
foo n f = do
let theBasis = (getBasis n) :: [a]
undefined
但是錯誤仍然存??在,并且將型別注釋移動到該行中的不同術語并不能修復錯誤。
我如何告訴型別檢查器我希望簽名中出現的型別getBasis n相同?afoo
uj5u.com熱心網友回復:
在這種情況下,最簡單的方法是只使用基礎,因為型別檢查器可以推斷出a你的意思:
愚蠢的例子:
foo :: Basis a => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis n
_ = map f theBasis
undefined
否則,您也可以使用型別注釋(需要ScopedTypeVariables擴展名,否則a函式體內部將不是a來自簽名):
foo :: forall a b. Basis a => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis n :: [a]
undefined
使用ScopedTypeVariables TypeApplications您還可以將型別引數顯式傳遞a給getBasis:
foo :: forall a b. Basis a => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis @a n
undefined
uj5u.com熱心網友回復:
最初的錯誤很可能發生,因為您在代碼中沒有任何其他內容可以指示theBasis編譯器的型別。例如,如果你只在運算式中使用它show theBasis,那么編譯器只知道該型別應該有一個Show實體,但它仍然不知道該型別是什么。
但是,您的修復嘗試更有趣。它揭示了潛在的問題。即使您明確指定型別應該是[a],編譯器仍然感到困惑。這是為什么?你說的是[a],編譯器還想要什么?
答案是ain(Basis a)和 a in :: [a]不一樣a!
在 Haskell 中,默認情況下,型別變數的范圍僅限于使用它們的型別簽名。所以在foo它的型別簽名中是一個a,本地的型別簽名。然后在它的型別簽名中,(getBasis n)它是一個完全不同的a、本地的型別簽名。
但是有一種方法可以告訴編譯器它應該是一樣的a。那種方式是forall:
foo :: forall a b. (Basis a) => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = (getBasis n) :: [a]
undefined
當顯式使用時,forall為其中列出的型別變數創建更廣泛的范圍。對于函式型別簽名,作用域是函式的整個主體。因此,ain:: [a]最終與ainfoo的簽名相同。
(請注意,您需要擴展才能使其ScopedTypeVariables正常作業)
uj5u.com熱心網友回復:
使用ScopedTypeVariables. 此擴展允許在函式體內的型別簽名中使用型別變數。注意,在某些情況下,我a可以從 推斷f,所以你擺脫了錯誤
{-# LANGUAGE ScopedTypeVariables #-}
class Basis a where
getBasis :: Int -> [a]
foo :: forall a b. (Basis a) => Int -> (a -> b) -> IO ()
foo n f = do
let theBasis = getBasis n :: [a]
undefined
-- Do some stuff with the basis using the function f.
-- theBasis should have type [a].
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/530198.html
標籤:哈斯克尔多态性类型错误
