我有以下应用表达,我知道这是错误的:
<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
应该使用哪种类型?
答案 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]