有人可以举例说明具有以下签名的函数:
f :: a -> b -> (a -> b)
f接受两个类型为a和b的参数,并返回一个函数,该函数接受类型为a的参数并返回类型为b的元素。
我们的老师今天给了我们这个额外的练习,并说它真的很难。我尝试使用lambda表达式编写它,但我失败了。
这是一项非常有趣的练习,如果有人知道该怎么做,请回答这个问题。谢谢!
答案 0 :(得分:5)
首先,我们可以省略括号,a -> b -> (a -> b)
与
a -> b -> a -> b
(这是因为currying)
现在看看这个签名。我们得到了以下输入:
a
b
我们需要返回b
类型的内容。但是现在看,只有一种方法可以做到这一点(如果我们暂时忽略undefined
),因为我们只得到一个b
类型的值!我们只是返回那个值:
f :: a -> b -> a -> b
f _ b _ = b -- We ignore both values of type a, because we cannot do anything with a's
所以上面我说只有一个解决方案,如果我们忽略undefined
,error ...
,let v = v in v
和类似的(那些被称为bottom值,因为它们要么崩溃程序或在评估时不会终止)。你能找到一个使用其中一个的定义吗?
修改强>
如评论中所述,此函数实际上具有更通用的类型。我假设练习是找到一个可以该类型的函数,而不是一个推断类型是给定类型的函数。如果那不是您想要的,请参阅@bheklilr's answer
如果您对简短但难以理解的定义感兴趣,请参阅codegolf上的类似问题
答案 1 :(得分:5)
类型a -> b -> a -> b
的函数可以表示为
f a1 b a2 = let xs = [a1, a2] in b
由于这会强制a1
和a2
具有相同的类型,以便位于同一列表中。 xs
的值刚刚被丢弃,然后我们返回b
。
另一个是
g a1 b a2 = let x = g a2 b a1 in b
根本不使用列表,而是使用非常类似的技术来欺骗编译器统一a1
和a2
的类型。
答案 2 :(得分:3)
f a' b a'' = const b (asTypeOf a' a'')
答案 3 :(得分:3)
最近出现了这样的问题。由于没有关于返回值的其他要求,您可以返回给定的b
,并忽略类型a
的两个值。 b->a->b
是const
。所以f _ = const
是最短的函数,它将忽略第一个和第三个参数,并返回与第二个参数相同类型的值。然而,它并没有将第一个和第三个参数的类型绑定为相同。我们可以通过将它们作为f的相同参数来提供。
最简单的方法之一是通过组合:f _ = (.f).const
现在因为第三个参数作为第一个参数被输入f
,这些参数的类型将是相同的。
答案 4 :(得分:2)
f a b c = const b (asTypeOf c a) -- answer by md2perpe
= const b (f c)
= const b . f $ c
= ((. f) . const) b c -- answer by Sassa NF
这是(递归)定义,而不是表达式。因此,如果您想要使用此签名找到表达式,
f = const ((. f) . const)
= (const . (. const)) (. f)
= ((const . (. const)) . flip (.)) f
= fix ((const . (. const)) . flip (.))
fix
来自Data.Function
。 asTypeOf
不是原始的组合子,因为它本身是使用显式类型签名asTypeOf :: a -> a -> a ; asTypeOf = const
定义的。建议使用[]
:
f a b c = const b ( (a:) . (c:) )
即 1
f = flip ((.) . const) . (. (:)) . (.) . (:)
选择毒药。 :)
1 由于某种原因,lambdabot在这里产生了错误的const const
(错误的一般签名)。我通过运行产生@pl \a b c -> const const b ( (a:) . (c:) )
的{{1}}来欺骗它。