编译器是什么意思?

时间:2017-08-22 07:21:37

标签: haskell

我有以下应用表达,我知道这是错误的:

<interactive>:2:2: error:
    * Couldn't match expected type `Maybe Integer -> b'
                  with actual type `Maybe (Integer -> Integer)'
    * Possible cause: `Just' is applied to too many arguments
      In the expression: Just (* 2)
      In the first argument of `(<*>)', namely `[Just (* 2), Just (+ 9)]'
      In the expression:
        [Just (* 2), Just (+ 9)] <*> [(Just 3), (Just 4), (Just 5)]
    * Relevant bindings include it :: [b] (bound at <interactive>:2:1)

并且编译器抱怨:

* Couldn't match expected type `Maybe Integer -> b'
              with actual type `Maybe (Integer -> Integer)'

编译器试图说什么?

此错误消息:

[Just (*2), Just (+9)]

它表示表达式的这部分(<*>)

让我们看一下函数(<*>) :: f (a -> b) -> f a -> f b 的签名:

List

将其替换为上面的Maybe(<*>) :: [] (Maybe Integer -> b) -> [] (Maybe Integer) -> [] b 类型构造函数:

b

Declare @T table(AGREEMENTID varchar(50),FeedbackDate varchar(50),DispositionCode varchar(10)) Insert into @T Select '0003SBML00151','2017-03-08 00:00:00.000','PTP' union all Select '0004SBHL00705','2017-03-17 00:00:00.000','BPTP' union all Select '0007SBML01987',NULL,NULL union all Select '0026MSS00108','2017-05-20 00:00:00.000','PTP' union all Select '0026MSS00108','2017-03-22 00:00:00.000','PTP' union all Select '0026MSS00108','2016-12-30 00:00:00.000','BPTP' union all Select '0026MSS00108','2016-12-29 00:00:00.000','BPTP' union all Select '0026MSS00108','2016-12-28 00:00:00.000','BPTP' union all Select '0037SBHL02361',NULL,NULL union all Select '0038SBML00291','2017-05-04 00:00:00.000','PTP' union all Select '0038SBML00291','2017-04-24 00:00:00.000','BPTP' union all Select '0038SBML00291','2017-04-11 00:00:00.000','NC' union all Select '0038SBML00291','2016-12-22 00:00:00.000','PTP' union all Select '0038SBML00291','2016-12-09 00:00:00.000','DC' Select 'L'+convert(varchar(255),ROW_NUMBER()over(partition by AGREEMENTID order by AGREEMENTID))'rno',* into test From @T order by AGREEMENTID declare @Levels nvarchar(max),@SQL NVARCHAR(MAX) select @Levels= STUFF((select DISTINCT ','+rno from test for xml path('')),1,1,'') SET @SQL= 'SELECT AGREEMENTID,'+@Levels+' FROM (select AGREEMENTID,DispositionCode,rno from test )as TEMP'+' PIVOT'+' (MAX(DispositionCode) FOR rno IN ('+@Levels+') )AS pvt' exec sp_executesql @SQL 应该使用哪种类型?

4 个答案:

答案 0 :(得分:3)

让我们更仔细地替换

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
[Just (*2), Just (+9)] :: [Maybe (Int -> Int)]   --wlog
[Just 3, Just 4, Just 5] :: [Maybe Int]

所以f = [],因此:

(<*>) :: [a -> b] -> [a] -> [b]

但现在我们要将[a -> b][Maybe (Int -> Int)]相匹配,这是不可能的 - 功能和Maybe不能相同。您正在尝试在两个仿函数下执行函数应用程序,而不只是一个。即你需要什么类型

f (g (a -> b)) -> f (g a) -> f (g b)

幸运的是,这很容易制作:liftA2 (<*>)

或者,如果你想要更高级的东西,你可以在复合仿函数Compose [] Maybe上操作。

getCompose $ Compose [Just (*2), Just (+9)] <*> Compose [Just 3, Just 4, Just 5]

(但是Compose很酷的时候就是你不立即getCompose结果,但是在你正在编写的任何程序中都将它作为一个重要的抽象。)

答案 1 :(得分:3)

编译器指的是代码的这一部分(In the expression: Just (* 2)):

[Just (*2), Just (+9)] <*> [(Just 3),(Just 4), (Just 5)]
 ^^^^^^^^^

它还说Just (*2)的实际类型为Maybe (Integer -> Integer),但您使用它的方式需要Maybe Integer -> b类型的值(对于某些人来说)输入b)。

如果你看一下

的类型
(<*>) :: f (a -> b) -> f a -> f b

您可以看到第一个参数必须是应用于函数类型f的某种类型构造函数a -> b。您有一个值列表,因此f[]

因此,第一个参数必须是函数列表,但您拥有的是Maybe的列表。这就是为什么这段代码是错误的。

错误消息的其余部分来自<*>[(Just 3),(Just 4), (Just 5)]的第二个参数,它是一个参数列表(对于第一个参数中的函数列表)。也就是说,编译器知道它需要f a类型的值,并且你给它[(Just 3),(Just 4), (Just 5)],因此它推导出f = []a = Maybe Integer

因此第一个参数f (a -> b)的类型变为[] (Maybe Integer -> b)(与[Maybe Integer -> b]相同)。 b这里完全免费。您可以使用所需的任何结果类型,然后从f b返回[b](即<*>(结果列表)。

答案 2 :(得分:2)

这里有一个错误的替代品:

(<*>) :: [] (Maybe Integer -> b) -> [] (Maybe Integer) -> [] b

[Just (*2), Just (+9)]具有以下类型:Num a => [Maybe (a -> a)]

那是因为List f中的(<*>) :: f (a -> b) -> f a -> f b

根据(<*>)的类型,您可以:

[(*2), (+9)] <*> [2, 3]

或者

Just (*2) <*> Just 2

[]以及Maybe将在这些表达式中相应地使用适用语境,但不能同时使用(<*>)

以下深奥的表达式将编译:

[(Just (*2) <*>), (Just (+9) <*>)] <*> [(Just 3), (Just 4), (Just 5)]

但我不确定这是你在寻找什么。

答案 3 :(得分:0)

Prelude> [Just (*2), Just (+9)] <*> [(Just 3),(Just 4), (Just 5)]

指令有两个仿函数。外部的一个是List,内部的是Maybe所以当你将<*>应用程序操作放在两个列表之间时,第一个列表应该包含一些函数类型元素,以成为一个applicative functor,例如;

Prelude> [(+1),(*2)] <*> [1,2]
[2,3,2,4]

但是在您的指令中,第一个列表只包含一些Maybe值。这并不能将列表限定为应用函子。但是列表的元素是Maybe (a -> b)类型。这意味着不是列表本身,但它的内容是适用的函子。因此,为了将我们的列表转换为应用列表,您应该使用带有应用Maybe (a -> b)Maybe a的函数替换应用的Maybe值,并给出Maybe b换句话说f (a -> b) -> f a -> f b这恰好是<*>运营商。

因此,如果您按照以下方式重新编写代码,您将获得预期的结果;

Prelude> (<*>) <$> [Just (*2), Just (+9)] <*> [(Just 3),(Just 4),(Just 5)]
[Just 6,Just 8,Just 10,Just 12,Just 13,Just 14]