函数const
在Prelude中定义为:
const x _ = x
在GHCi中,当我尝试
时Prelude> const 6 5 -> Gives 6
但是当我尝试
时Prelude> const id 6 5 -> Gives 5
即使在进行了像
这样的更改之后Prelude> (const id 6) 5 -> Gives 5
此函数不应该给6
,因为函数id
的输出具有应该绑定的类型id :: a -> a
Prelude> (const 6) 5 -> Gives 6
为什么函数const
的行为有所不同?
答案 0 :(得分:63)
您似乎认为这相当于const (id 6) 5
,其中id 6
的计算结果为6,但事实并非如此。如果没有这些括号,您将id
函数作为第一个参数传递给const
。请再次查看const
的定义:
const x _ = x
这意味着const id 6 = id
。因此,const id 6 5
相当于id 5
,实际上是5。
答案 1 :(得分:14)
函数也可以是其他函数的参数。 id 成为 const 的参数。
(const id 6)5 的表达方式实际上是:
(const id 6)5
(const id _)5 - 抓住第一个参数 id
id 5
5
有关运营商真正做的更多细节:
一对括号中的任何内容都将被视为整个表达式(但并不意味着它将首先计算)。例如:(地图(1 +)),(\ x - >( - )x)
前缀运算符绑定比中缀运算符更强
表达式中最左边的前缀运算符将被视为一个函数,它从左到右抓取表达式中的参数(包括其他前缀运算符),直到面向中缀运算符或行尾。例如,如果您在GHCi中键入 map(+)id 3 const + 2 ,您将收到一条错误,上面写着“函数`map'应用于四个参数......”因为地图在中缀运算符之前抓取(+), id , 3 和 const 作为参数的 + 强>
答案 2 :(得分:5)
Chuck is right,Haskell中的函数应用程序是left associative,这意味着像f a b c
这样的函数调用等同于(((f a) b) c)
。请记住,在Haskell中,您应该始终练习查看函数类型,并尝试根据函数类型推断函数可以做什么和不可以做什么。起初你可能无法从函数类型中推断出任何东西,但是有了更多经验,类型信息将变得不可或缺。
const
的类型是什么?在GHCi中输入:t const
。它将返回const :: a -> b -> a
。 a
和b
为type variables,这意味着const将接受任何类型的参数。由于1 st 和2 nd 参数具有不同的类型,您几乎可以将所有内容传递给函数:
const 1 2 -- returns 1
const 'a' 1 -- returns 'a'
const [1,2,3] "a" -- returns [1,2,3]
const
的类型变量可能存在特定的typeclass constraints会阻止传递函数,例如Num
或Ord
,因为函数不是实例这些类型。换句话说,函数不会表现为数字或有序事物,因此f + g
或f < g
没有意义。但是const
没有类型类约束阻止我们将函数作为参数传递。请记住,Haskell支持higher-order functions?这意味着Haskell的函数可以接受并返回其他函数。因此:
const (+) (*) -- returns (+)
const head tail -- returns head
const id 2 -- returns id
const
只是忽略2 nd 参数并返回作为1 st 参数传递的任何内容,无论是Char,String,Integer,Maybe, [],一些非常复杂的代数数据类型,甚至是函数。
如果const
的类型为a -> b -> a
,您是否可以在没有在GHCi中输入const 'a'
的情况下找出:t const 'a'
而没有找到它的类型?要找出const 'a'
的类型,用1 st 参数的类型代替所有相同的类型变量,然后从类型中删除第一个参数。
a -> b -> a
:原始类型Char -> b -> Char
:在类型变量a b -> Char
:通过从类型声明中删除第一个参数的新函数的类型那么const id
的类型是什么?
a -> b -> a
:原始类型(a -> a) -> b -> (a -> a)
:替换b -> (a -> a)
:结果类型(删除第一个参数)b -> a -> a
:与上述相同,->
运算符为right-associative <强>练习:强>
const (+)
,const head
,const tail
,const (++)
,{{ 1}}