作为我之前问题的后续一起使用 makeLenses、类约束和类型同义词 https://stackoverflow.com/questions/30582583/using-makelenses-class-constraints-and-type-synonyms-together我有一个新类型的错误,我想了解一下。
类型错误是由于类型同义词的引入引起的type S = (Num n) => State n
在下面的例子中。
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RankNTypes #-}
module Foo where
import Control.Lens
data State a = State { _a :: a
} deriving Show
makeLenses ''State -- Requires TemplateHaskell
-- | Smart constructor enforcing class constraint on record field _a.
mkState :: (Num a) => a -> State a
mkState n = State {_a = n}
doStuff1 :: Num a => State a -> State a
doStuff1 s = s & a %~ (*2)
test1a = doStuff1 $ mkState 5 -- results in State {_a = 10.0}
test1b = doStuff1 $ mkState 5.5 -- results in State {_a = 11.0}
type S = (Num n) => State n -- Requires the RankNTypes extensions
doStuff2 :: S -> S
doStuff2 s = s & a %~ (*2)
test2a = doStuff2 $ mkState 5 -- Results in State {_a = 10.0}
--test2b = doStuff2 $ mkState 5.5 -- Type error.
如果我取消注释test2b
我收到以下错误。
Could not deduce (Fractional n) arising from the literal `5.5'
from the context (Num n)
bound by a type expected by the context: Num n => State n
at Foo.hs:32:10-32
Possible fix:
add (Fractional n) to the context of
a type expected by the context: Num n => State n
In the first argument of `mkState', namely `5.5'
In the second argument of `($)', namely `mkState 5.5'
In the expression: doStuff2 $ mkState 5.5
我希望能够理解为什么引入的类型同义词会导致此错误以及如何破译错误消息。
S -> S
不等于forall n. Num n => State n -> State n
。它相当于(forall n. Num n => State n) -> (forall n. Num n => State n)
。前者意味着,对于所有数字类型n
,我们可以传入一个State n
并取回State n
(对于同类型n
)。后者意味着我们传递的东西可以是State n
对于所有数字类型n
我们得到的东西可以是State n
对于所有类型n
。换句话说,参数和结果都是多态的。
这意味着您传入的参数必须具有类型Num n => State n
,不是更具体的类型,例如,State Int
。这对于5
,其类型为Num n => n
, 但不是5.5
,其类型为Fractional n => n
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)