首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell“申请”?

Haskell“申请”?
EN

Stack Overflow用户
提问于 2012-05-26 23:15:34
回答 3查看 10.4K关注 0票数 20

可能重复:

Why is such a function definition not allowed in haskell?

我是Haskell世界的新手,从Lisp迁移过来的。我正在努力适应Haskell完全不同的世界观,我发现许多新的和令人兴奋的事情之一就是类型系统。作为Lisper的一员,我想我应该尝试在Haskell中实现一个在Lisp世界中非常重要的函数:apply。对于那些不知道的人,apply接受一个函数和一组参数,并对这些参数调用函数。在Scheme中,(apply + '(1 2 3))与调用(+ 1 2 3)相同,返回6。

我的Haskell代码看起来像这样:

代码语言:javascript
复制
apply x [] = x
apply f (x:xs) = apply (f x) xs

但Haskell抱怨道:

代码语言:javascript
复制
ERROR line 2 - Type error in function binding
*** Term           : apply
*** Type           : (b -> a) -> [b] -> a
*** Does not match : a -> [b] -> a
*** Because        : unification would give infinite type

我想我明白为什么。Apply的类型需要根据给定列表的长度而有所不同。假设有3个项目的列表,apply的类型需要是:(a -> a -> a -> b) -> [a] -> b,但是如果有6个项目的列表,apply的类型需要是:(a -> a -> a -> a -> a -> a -> b) -> [a] -> b

我尝试了这个可怕的变通方法:

代码语言:javascript
复制
data FnOrDat a b = Dat b | Fn (a -> FnOrDat a b)

apply :: (FnOrDat a b) -> [a] -> (FnOrDat a b)
apply x [] = x
apply (Fn f) (x:xs) = apply (f x) xs
apply (Dat _) _ = error "Cannot apply something which is not a function!"

add a = Fn (\b -> Dat (a + b))

main = putStrLn $ show $ x where Dat x = apply (Fn add) [5,1]

这是可行的,但它几乎不能算作apply函数,因为我不能传递给apply一个普通的函数,我必须使用专门编写的函数来使用我的(笨拙的) FnOrDat抽象。如果我想写一个将四个数字相加的函数,我需要写

代码语言:javascript
复制
add4 a = Fn (\b -> Fn (\c -> Fn (\d -> Dat (a + b + c + d))))

真恶心。

那么,我是不是遗漏了什么,或者是在请求一个通用的apply,就像请求一个可以操作任意长度元组的函数一样?apply在Haskell的静态类型世界观中有意义吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-26 23:21:02

apply在Haskell中不是很有用,因为你不能给函数指定类型。正如您在FnOrDat中看到的,您实际上是将Lisp语言作为EDSL嵌入到Haskell中,以强制某些内容通过。

请求通用的

基本上就像请求一个可以操作任意长度元组的函数一样?

一点儿没错。您可以为某些有用的类型组合提供类型类实例,但实际上并不需要或使用通用的可变apply

顺便说一句,你应该考虑升级到GHC和Haskell Platform,而不是过时的Hugs系统,因为你错过了过去10年开发的大多数库、工具和语言功能。

票数 11
EN

Stack Overflow用户

发布于 2012-05-26 23:36:49

尽管唐的解释,foldl1 (+)实际上会添加列表的所有元素。因此,可以说,正如OP所描述的那样,fold函数族非常接近于apply

票数 4
EN

Stack Overflow用户

发布于 2012-05-28 22:39:02

...在Lisp世界中有一个非常重要的函数:应用。对于那些不知道的人,apply接受一个函数和一组参数,并对这些参数调用函数。在方案中,(apply + '(1 2 3))与调用(+ 1 2 3)相同,并返回6。..。

这很简单:

代码语言:javascript
复制
foldr  (+) 0 [1,2,3]
foldr1 (+)   [1,2,3]

结果是6。

要将函数应用于列表的每个元素,请执行以下操作:

代码语言:javascript
复制
map f list

例如:

代码语言:javascript
复制
map (2*) [1,2,3]

2,4,6中的结果

这就是你要找的东西吗?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10767407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档