在REPL中,这有效:
> mm n = (\n -> n * 2) <$> n
> mm (2:3:Nil)
(4 : 6 : Nil)
在这个编译的文件中,我可以运行它:
squareOf ls =
map (\n -> n * n) ls
然而,当我向该函数添加类型定义时
squareOf :: List Int -> Int
squareOf ls =
map (\n -> n * n) ls
我收到错误:
Could not match type
List Int
with type
Int
while checking that type t0 t1
is at least as general as type Int
while checking that expression (map (\n ->
(...) n
)
)
ls
has type Int
in value declaration squareOf
where t0 is an unknown type
t1 is an unknown type
我尝试将签名更改为列表的类型别名,并且我尝试了一个没有运气的定义。 如果我检查创建的定义,当我不在我的函数中添加签名时,我得到:
forall t2 t3. Functor t2 => Semiring t3 => t2 t3 -> t2 t3
任何人都可以解释为什么我的签名不正确以及为什么我会为该功能获得此签名?
干杯
编辑:感谢您的评论,更新fn定义,以便它返回List Int
,当然,它解决了问题
答案 0 :(得分:2)
假设你的repl函数是你所追求的行为,你在后面的定义中错过了地图运算符(<$>
)。
您的repl函数(为了清晰起见,重命名了变量)的类型为:
mm :: forall f. Functor f => f Int -> f Int
mm ns = (\n -> n * 2) <$> ns
这就是说: mm将“两次”映射到可映射的东西“(即一个Functor)
除此之外:您的定义可以更加简洁明了:
mm :: forall f. Functor f => f Int -> f Int
mm = map (_*2)
这类似于您的squareOf
定义,只是现在您正方形,因此您对(*)
的使用更为通用:
squareOf :: forall f. Functor f => Semiring n => f n -> f n
squareOf = map \n -> n * n
因为(*)
是Semiring类型类的成员。
但你给它的签名表明你是在追求某种fold
?让我知道您对squareOf
函数的期望输出,我会相应地更新答案。
答案 1 :(得分:1)
以下是map
:
class Functor f where
map :: forall a b. (a -> b) -> f a -> f b
缩小到List Int
和Int -> Int
,编译器推断
map :: (Int -> Int) -> List Int -> List Int
因此,在squareOf
中,表达式会缩减为整数列表,而不是整数。这就是编译器抱怨的原因。