如何在Haskell中部分定义函数签名? [英] How to define function signatures partially in Haskell?

查看:113
本文介绍了如何在Haskell中部分定义函数签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出发点:

  fn :: [a]  - > Int 
fn =(2 *)。长度

假设我们只有要约束返回值,那么我们可以这样写:

  fn list =(2 * length list):: Int 

只限制 的参数如何?很容易。

  fn list = 2 * length(list :: [Char])

虽然这可行,但最好在顶部收集签名
,而不是分散在函数体中。



这是我能找到的最接近的:

  fnSig = undefined: :[Char]  - > a 
fn | False = fnSig
| True =(* 2)。长度

根据 -sigs> http://okmij.org/ftp/Haskell/types.html#partial-sigs



但是,我想要一个清洁工解。
更好的沟通,我的意图是部分限制。
类似于此,例如:

  fn :: [Char]  - > a 
fn =(2 *)。长度

或者:

  fn :: [Char]  - > _ 
fn =(2 *)。长度

这可能吗?

编辑进一步澄清: b
$ b

@GaneshSittampalam在下面的评论中提出了一个重要观点。
我正在寻找完全没有任何类型签名的中间房屋,并且必须提供确切的房子。所以,我不是在寻找一个基于TypeClass的答案,我只是想让GHC填充我的函数的未指定(或未完全限制)类型的空白。



编辑回复@WillNess



是的,像这样...

  fn list = 2 *长度列表
其中
_ = list :: [Char]

...可以工作,但仅适用于参数,并且只有在函数不是无点的时候。有没有办法将这种技术应用于无点函数或返回值?



编辑回复@Rhymoid



  fn =(2 * )。长度
其中
_ = fn`asTypeOf`(undefined :: [Char] - > a)
_ = fn`asTypeOf`(undefined :: a - > Int)
_ = fn`asTypeOf`(undefined :: a - > b)
_ = fn`asTypeOf`(undefined :: a)

这种方法还会限制fn的类型签名,并且不会污染任何名称空间。

通常我们只有一个在 asTypeOf 行中,我只是添加了多个来展示这种方法的强大程度。



它比我想要的更笨拙,但我认为它非常简洁,即使没有语言的特定语法支持,我们也可以做到这一点。



@Rhymoid,如果您也喜欢,请将其添加到您的答案中。 :)

对于自我推销感到抱歉,但这个特征恰恰是博士最近发表的论文的主题。学生Thomas Winant,我自己,Frank Piessens和Tom Schrijvers,最近由Thomas在2014年PADL研讨会上发表。有关完整的论文,请参阅此处。这是一个已经存在于其他语言中的功能,但与Haskell GADT等功能的交互使得它足够有趣,可以计算出细节。

Thomas正在为GHC开展一项实施工作。自文件撰写以来,它进一步改进,但在GHC中实施通配约束在技术上比我们预期的要难一些。我们希望能够进一步开展工作,并联系GHC开发人员以获得通过,但是否发生这种情况可能取决于有多少人希望在Haskell中具有该功能...



更新14-4-2015:经过Thomas的大量工作以及SPJ和其他GHC人员的意见后,部分类型签名已在GHC 7.10中发布。 Thomas Winant写了介绍性博客文章,介绍你如何可以使用它们。


Starting point:

fn :: [a] -> Int
fn = (2 *) . length

Let's say we only want to constrain the return value, then we could write:

fn list = (2 * length list) :: Int

How about restricting only the argument? Easy.

fn list = 2 * length (list :: [Char])

While this works, it would be preferable to have the signatures at the top collected and not scattered around the function body.

This is the closest I could come to this:

fnSig = undefined :: [Char] -> a
fn | False = fnSig
   | True  = (* 2) . length

Based on http://okmij.org/ftp/Haskell/partial-signatures.lhs via http://okmij.org/ftp/Haskell/types.html#partial-sigs

However, I'd like a cleaner solution. Something that communicates better that my intent is partial restriction. Something like this, for example:

fn :: [Char] -> a
fn = (2 *) . length

Or maybe:

fn :: [Char] -> _
fn = (2 *) . length

Is this possible?

Edit for further clarification:

@GaneshSittampalam Made an important point in a comment below. I am looking for "a half-way house between no type signature at all and having to give a precise one". So, I am not looking for a TypeClass-based answer, I just want GHC to fill in the blanks for the unspecified (or not fully restricted) types of my function.

Edit in response to @WillNess

Yes, something like this...

fn list = 2 * length list
  where
    _ = list :: [Char]

...could work, but only for arguments, and only if the function is not point-free. Is there a way to apply this technique to point-free functions or return values?

Edit in response to @Rhymoid

I got inspired, and played around with @Rhymoid's idea, and came up with this:

fn = (2 *) . length
  where
    _ = fn `asTypeOf` (undefined :: [Char] -> a)
    _ = fn `asTypeOf` (undefined :: a -> Int)
    _ = fn `asTypeOf` (undefined :: a -> b)
    _ = fn `asTypeOf` (undefined :: a)

This approach also restricts fn's type signature, and doesn't pollute any namespace.

Ordinarily we would only have one of the asTypeOf lines, I just added multiple to showcase how powerful this approach is.

It is a little more clumsy than how I would like it, but I guess it is pretty neat we can do this even without specific syntactic support from the language.

@Rhymoid, if you like it too, please add it to your answer. :)

解决方案

Sorry for the self-promotion, but exactly this feature is the topic of a recent paper by Ph.D. student Thomas Winant, myself, Frank Piessens and Tom Schrijvers, very recently presented by Thomas at the PADL 2014 symposium. See here for the full paper. It is a feature that is already present in some other languages, but the interaction with features like Haskell GADTs made it interesting enough to work out the details.

Thomas is working on an implementation for GHC. It has further improved since the writing of the paper, but implementing the "wildcard constraint" in GHC is technically a bit harder than we expected. We expect to be able to work further on it and contact the GHC developers to get it adopted, but whether or not this happens may depend on how much people would like to have the feature in Haskell...

Update 14-4-2015: After a lot of work by Thomas and input from SPJ and other GHC people, partial type signatures have been released in GHC 7.10. Thomas Winant wrote an introductory blog post about how you can use them.

这篇关于如何在Haskell中部分定义函数签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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