考慮 Haskell 函式
test :: ST s [Int]
test = do
arr <- newListArray (0,9) [0..9] :: ST s (STArray s Int Int)
let f i = do writeArray arr i (2*i)
readArray arr i
forM [1,2] f
和
test' :: ST s [Int]
test' = do
arr <- newListArray (0,9) [0..9] :: ST s (STArray s Int Int)
let f = \i -> do writeArray arr i (2*i)
readArray arr i
forM [1,2] f
第一個需要 FlexibleContexts 在 ghci 8.10.1 上編譯,第二個編譯沒有額外的選項。為什么?
s特別歡迎根據型別變數的范圍解釋這種行為的答案。作為后續,可以將什么(如果有)型別簽名添加到函式中以在沒有 FlexibleContexts的情況下f進行編譯?test最后,與單態限制有聯系嗎?
uj5u.com熱心網友回復:
您可以f在 GHCi 中檢查 GHC 分配給哪種型別:
ghci> import Data.Array
ghci> import Data.Array.MArray
ghci> let arr :: STArray s Int Int; arr = undefined
ghci> :t \i -> do writeArray arr i (2*i); readArray arr i
\i -> do writeArray arr i (2*i); readArray arr i
:: (MArray (STArray s1) Int m, MArray (STArray s2) Int m) =>
Int -> m Int
這比您在評論中建議的型別和FlexibleContexts需要的原因更籠統。
您可以添加您建議的型別簽名 ( Int -> ST s Int) 以避免必須使用FlexibleContexts:
{-# LANGUAGE ScopedTypeVariables #-}
...
test :: forall s. ST s [Int]
test = do
arr <- newListArray (0,9) [0..9] :: ST s (STArray s Int Int)
let
f :: Int -> ST s Int
f i = do
writeArray arr i (2*i)
readArray arr i
forM [1,2] f
請注意,作用域型別變數和forall s.此處是必需的,因為您需要確保s所有型別簽名中的 都參考相同的型別變數,并且不要全部引入新的型別變數。
單態限制以不同方式對待您的第一個和第二個版本的原因是因為它不適用于看起來像函式的東西。在你的第一個版本f中有一個引數,所以它看起來像一個函式,因此會得到一個通用型別。在您的第二個版本f中沒有引數,因此它看起來不像一個函式,這意味著單態限制迫使它具有更具體的型別。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/423016.html
標籤:
