类型同义词导致类型错误

Kar*_*und 3 haskell

作为我上一个问题的后续使用makeLenses,类约束和类型同义词,我有一个新的类型错误,我想了解.

类型错误是由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.
Run Code Online (Sandbox Code Playgroud)

如果我取消注释,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
Run Code Online (Sandbox Code Playgroud)

我希望能够理解为什么引入的类型同义词会导致此错误以及如何解密错误消息.

sep*_*p2k 9

S -> S不等于forall n. Num n => State n -> State n.它相当于(forall n. Num n => State n) -> (forall n. Num n => State n).前者意味着,对于所有数字类型n,我们可以传入a 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.