Haskell 这是有效类型吗?我如何满足它?(由两个并矢函数组成)
我的问题很简单,作为haskell的初学者,我一直在思考类型、函数组合以及如何应用它们。我开始思考Haskell 这是有效类型吗?我如何满足它?(由两个并矢函数组成),haskell,composition,Haskell,Composition,我的问题很简单,作为haskell的初学者,我一直在思考类型、函数组合以及如何应用它们。我开始思考(+)(*)的结果可能是什么 现在很明显,这个问题的解决方案是打开ghci并找出答案。因此,我这样做并检查了类型: λ> :t ((*) . (+)) ((*) . (+)) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a 这种类型可能吗?我在努力理解它可能是什么或者它意味着什么 再次为这个简单化的问
(+)(*)
的结果可能是什么
现在很明显,这个问题的解决方案是打开ghci并找出答案。因此,我这样做并检查了类型:
λ> :t ((*) . (+))
((*) . (+)) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
这种类型可能吗?我在努力理解它可能是什么或者它意味着什么
再次为这个简单化的问题道歉,我尝试输入函数的所有内容都失败了。我只是想用并矢函数来发展函数合成的直觉。不幸的是,GHC并没有给出一个很好的信息。这几乎肯定不是你想要的。默认情况下,
Num(a->a)
没有实例,实现一个实例可能对某些事情有用,但可能会导致非常不直观的运行时错误。即使在这种情况下,此函数也不太可能有用
让我们看看类型受限的(*)
和(+)
,以简化情况并避免增加类型类的复杂性:
(*!) :: Int -> Int -> Int
(*!) = (*)
(+!) :: Int -> Int -> Int
(+!) = (+)
现在当我们尝试
λ> :t (*!) . (+!)
<interactive>:1:8:
Couldn't match type ‘Int -> Int’ with ‘Int’
Expected type: Int -> Int
Actual type: Int -> Int -> Int
Probable cause: ‘(+!)’ is applied to too few arguments
In the second argument of ‘(.)’, namely ‘(+!)’
In the expression: (*!) . (+!)
(*!)
的左参数是一个函数,它与预期的Int
类型不匹配
用两个参数的函数组合
为此,我们需要一个函数(b->c)->(a1->a2->b)->a1->a2->c
。幸运的是,这正是()
的含义
λ> :t ((.) . (.)) (*!) (+!)
((.) . (.)) (*!) (+!) :: Int -> Int -> Int -> Int
有些库以(.:)
(like)的名称提供此功能。有时人们喜欢写它fmap。fmap
(但这不仅仅是普通函数的组合)
但这有点神秘,因此通常避免使用。明确地写出函数几乎总是更清楚的。这是一个有趣的问题 首先,我将解释为什么你会得到你所做的类型 (+)和(*)都具有类型
Num a=>a->a->a
这基本上意味着它们有两个数字作为输入,输出一个数字(正如加法和乘法所期望的那样)
函数组合将(a->b)类型的两个函数链接在一起(当然,第一个函数的输出需要与下一个函数的输入类型相同)
因此,乍一看,(+)或(*)似乎都不是那种类型。。。。除了在哈斯凯尔的世界里,你可以把他们看作是一种类型
(+)::Num a=>a->(a->a)
这是有道理的。。。。例如,如果您填入一个(+)值,您将得到一个函数,该函数将一个数字的值增加该值
(+) 1 --evaluates to incrementByOne
where incrementByOne x = 1+x
因此,您可以将这两个链接在一起,但是
记住(*)的输入必须是数字!(因为numa=>
)
将(.)应用于(+)和(*)将生成您的类型
(Num (a -> a), Num a) => a -> (a -> a) -> a -> a
但是,它有一个奇怪的约束Num(a->a)
,它规定一个函数必须是一个数字。这基本上是不应该做的,但是Haskell中没有禁止它的内容,因此编译器在这一点上没有抱怨。只有当您尝试使用该函数时,它才会执行检查
((+) . (*)) 1 (+ 1) 2
<interactive>:16:1:
No instance for (Num (a0 -> a0)) arising from a use of ‘it’
In a stmt of an interactive GHCi command: print it
(+).(*)1(+1)2
:16:1:
没有因使用“it”而产生的(Num(a0->a0))实例
在交互式GHCi命令的stmt中:打印它
三个输入具有正确的类型,但约束除外。。。。解释器在这里抱怨函数(+1)不是一个数字。数字函数不是前奏曲中的
Num
,但是如果您自己或导入为Num b=>a->b
编写一个Num
实例,您可以满足这个要求。@genisage对不起,我不完全理解您的意思?我怎样才能满足这个要求?我主要是想了解这个类型意味着什么以及这个类型签名意味着什么,所以如果你能给出一个具体的例子,说明什么可以满足它(事实上,把它作为一个答案发布),这将帮助我加载;(+)=liftA2(+);(*)=liftA2(*);(-)=liftA2(-);否定=fmap否定;信号=fmap信号;abs=fmap absWow,这个数据合成链接非常棒,肯定澄清了很多。谢谢。@MikeH-R这将略过前面一点,但是关于透镜的讨论是沿着这种多元函数组合的思路进行的(以及关于组合fmap
s的更一般的想法):太棒了,我一直在努力学习一些关于透镜的知识(上周写下了我的第一篇拙劣的半理解的实现)因此,非常感谢您的推荐。谢谢谢谢你,这就解释了我对它最初为什么要编译的误解。
(Num (a -> a), Num a) => a -> (a -> a) -> a -> a
((+) . (*)) 1 (+ 1) 2
<interactive>:16:1:
No instance for (Num (a0 -> a0)) arising from a use of ‘it’
In a stmt of an interactive GHCi command: print it