Haskell“应用”? [英] Haskell "Apply"?

查看:149
本文介绍了Haskell“应用”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能存在重复:

为什么在haskell中不允许这样的函数定义?

我是Haskell世界的新手,从Lisp移植过来。我试图调整到Haskell的根本不同的世界观,我发现很多新事物和令人兴奋的事情之一就是类型系统。作为一个Lisper,我想我会尝试在Haskell中实现一个在Lisp世界中非常重要的函数: apply 。对于那些不知道的人来说,应用程序需要一个函数和一个参数列表,然后调用这些参数的函数。在Scheme中,(apply +'(1 2 3))与调用(+ 1 2 3) ,并返回6。



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

  apply x [] = x 
apply f(x:xs)= apply(fx)xs

但Haskell抱怨:

 错误第2行 - 函数绑定中输入错误
***术语:申请
***类型:(b - > a) - > [b] - > a
***不符:a - > [b] - > a
***因为:统一会给无限类型

我认为我明白为什么。应用的类型需要根据列表的长度而有所不同。给定3个项目的列表,申请的类型将需要:(a - > a - > a - > b) - > [a] - > b ,但给定一个6项列表,apply的类型将需要:(a - > a - > a - > a - > a - > ; a - > b) - > [a] - > b



我试过这种可怕的解决方法:

 数据FnOrDat ab = Dat b | Fn(a  - > FnOrDat a b)

apply ::(FnOrDat a b) - > [a] - > (FnOrDat ab)
apply x [] = x
apply(Fn f)(x:xs)= apply(fx)xs
apply(Dat _)_ = error这不是一个功能!

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

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

这可以起作用,但它很难算作 apply 函数,因为我不能传递 apply 一个普通函数,所以我必须使用一个专门用来使用我的(笨拙的)FnOrDat抽象。如果我想编写一个添加了四个数字的函数,我需要编写

  add4 a = Fn(\ b  - > Fn(\ c→Fn(\ d→Dat(a + b + c + d))))

Ew。

所以 - 我错过了什么,或者是要求一个通用的 apply 基本上就像要求一个可以操纵任意长度元组的函数一样?在Haskell的静态类型世界观中,是否适用甚至是有意义的?

解决方案

apply 在Haskell中并不是很有用,因为你不能为该函数提供一个类型。正如你在FnOrDat中看到的那样,你实际上是在Haskell中嵌入了一个Lisp语言作为EDSL来强制通过。


要求一个通用的基本上就像申请一个可以操纵任意长度元组的函数一样适用?


正是。您可以为某些有用的类型组合提供类型类实例,但对于一般可变参数 apply 并不需要或不需要使用。




作为一个附注,你应该考虑升级到GHC和 Haskell Platform ,而不是过时的Hugs系统,因为您错过了过去10年中开发的大多数库,工具和语言功能。


Possible Duplicate:
Why is such a function definition not allowed in haskell?

I'm a newcomer to the world of Haskell, migrating over from Lisp. I'm trying to adjust to Haskell's fundamentally different worldview, and one of the many things that I find new and exciting is the type system. Being a Lisper, I thought I would try to implement in Haskell a function which is very important in the Lisp world: apply. For those who don't know, apply takes a function and a list of arguments, and invokes the function on those arguments. In Scheme, (apply + '(1 2 3)) is the same as invoking (+ 1 2 3), and returns 6.

My Haskell code looks something like this:

apply x [] = x
apply f (x:xs) = apply (f x) xs

But Haskell complains:

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

And I think that I understand why. Apply's type needs to be different depending on the length of the list it is given. Given a list of, say, 3 items, apply's type would need to be: (a -> a -> a -> b) -> [a] -> b, but given a list of 6 items, apply's type would need to be: (a -> a -> a -> a -> a -> a -> b) -> [a] -> b.

I tried this horrendous work-around:

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]

This works, but it hardly counts as an apply function, because I can't pass apply a normal function, I have to use one that has been written specifically to use my (awkward) FnOrDat abstraction. If I wanted to write a function that added four numbers, I would need to write

add4 a = Fn (\b -> Fn (\c -> Fn (\d -> Dat (a + b + c + d))))

Ew.

So - am I missing something, or is asking for a general-purpose apply basically like asking for a function that can manipulate an arbitrary-length tuple? Does apply even make sense in the statically-typed worldview of Haskell?

解决方案

apply isn't very useful in Haskell, since you can't give a type to the function. As you see in your FnOrDat, you're essentially embedding a Lisp language into Haskell as an EDSL to force something through.

asking for a general-purpose apply basically like asking for a function that can manipulate an arbitrary-length tuple?

Exactly. You can come up with type class instances for certain useful combinations of types, but there's just not really a need or use for a general variadic apply.


As a side note, you should consider upgrading to GHC and the Haskell Platform, instead of the obsolete Hugs system, since you're missing out on most of libraries, tools and language features developed in the last 10 years.

这篇关于Haskell“应用”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆