haskell - 类型同义词导致类型错误

标签 haskell

作为我上一个问题的后续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 => 状态 n -> 状态 n。它相当于 (forall n.Num n => State n) -> (forall n.Num n => State n)。前者意味着,对于所有数字类型n,我们可以传入一个State n并返回一个State n(对于相同的输入n)。后者意味着我们传入可以是所有数字类型 nState n 的东西,并且我们返回可以是 State n 的东西> 对于所有类型n。换句话说,参数和结果都是多态的。

这意味着您传入的参数必须具有类型 Num n => State n,而不是更具体的类型,例如 State Int。对于 5 来说是这样,它的类型为 Num n => n,但 5.5 则不然,它的类型为 Fractional n => n.

关于haskell - 类型同义词导致类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31772516/

相关文章:

haskell - 如何从 Haskell 程序中访问 "+RTS -s"或其他内存信息?

list - Data.map 中 haskell 列表的复杂性

haskell - 如何在 Haskell 中对中间值进行模式匹配

haskell - 如何安装system.random。也许版本8中的阴谋问题

haskell - Haskell中有一些目录步行者吗?

haskell - 为什么存在bind(>>=)?没有绑定(bind)的解决方案很丑陋的典型情况是什么?

c++ - haskell 中用多态性替换条件的等效模式是什么?

haskell - 直觉类型理论的组合逻辑等价物是什么?

parsing - Haskell:尽管文件中有更多输入,但解析文件在第一个表达式后完成

haskell - $(美元)和$!之间有什么区别? (美元感叹号)