繁体   English   中英

haskell:调用具有不同类型列表的函数

[英]haskell: calling a function with different types of lists

我有一个功能:

sum f l1 l2 = (f l1) + (f l2)

当用不同类型的列表调用时,如何使此函数正常工作? 例如:

sum length [1,2] ['a','b']

也可以在回答中充实我的评论。 可能会尝试给出的通常的签名是

sum :: Num b => ([a] -> b) -> [a] -> [a] -> b
sum f l1 l2 = f l1 + f l2

这里的问题是两个列表必须具有相同的类型,该类型必须是函数的输入类型。 解决方案是告诉GHC,该函数实际上对于所有forall a. [a] -> b具有更通用的类型forall a. [a] -> b forall a. [a] -> b ,这意味着我们可以选择多个可能不同 a实例,并且它们都产生相同的b

{-# LANGUAGE RankNTypes #-}

sum' :: Num b => (forall a. [a] -> b) -> [c] -> [d] -> b
sum' f l1 l2 = f l1 + f l2

main = print $ sum' length [1,2] ['a','b']

不幸的是,目前没有通用的方法可以做到这一点。 您可以尝试像下面这样的先前答案

sum' :: Num b => (forall a. [a] -> b) -> [c] -> [d] -> b
sum' f l1 l2 = f l1 + f l2

而同时这个作品与length ,它并没有真正与其他许多工作。

问题是此答案中的类型签名Num b => forall a. [a] -> b Num b => forall a. [a] -> b 这意味着您的函数必须适用于所有类型的列表,并且Num b => forall a. [a] -> b唯一有意义的函数Num b => forall a. [a] -> b Num b => forall a. [a] -> blength 如果您认为还有一个例子可以给我,但是我怀疑所有其他例子都是长度的变化或愚蠢的返回常数。

如果lengthsum'的唯一明智的论点,那么定义sum'是很愚蠢sum' ,您sumLength好像下面这样定义sumLength

sumLength :: Num b => [c] -> [d] -> b
sumLength l1 l2 = genericLength l1 + genericLength l2

实际上,让我们定义以下内容:

g :: Enum a => [a] -> Int
g = (foldl' 0 (+)) . (map fromEnum)

这是一个很奇怪的可能没用的功能,但是它做了一些微不足道的事情。 它将所有值转换为它们的Enum int表示形式,并对它们求和并吐出一个Integer。

因此sum' g l1 l2应该起作用,但事实并非如此。 为了使它起作用,您必须定义一个新函数:

sum'' :: Enum c, Enum d => (Enum a => forall a. [a]) -> [c] -> [d] -> Int
sum'' f l1 l2 = f l1 + f l2

确实,也要使用具有不同约束的任何函数,就必须定义sum的新版本。

所以,真的,没有,没有办法类似地回答您的问题。

我意识到了这个问题,并创建了polydata软件包,您可以检查黑客事件(我承认需要一些更清晰的文档)。

它确实允许您制作接受多态函数的函数,这些函数可以应用于不同的类型,如下所示:

g :: (c (a -> a'), c (b -> b')) => Poly c -> (a, b) -> (a' -> b')
g f (x,y) = (getPoly f x, getPoly f y)

这与您的示例非常相似。

上面的c是一个约束,查看g的类型应该可以帮助您了解正在发生的事情。

不幸的是,您不能仅仅将一个普通函数传递给g ,而必须传递一个包装在Poly函数,这是不平凡的,因为您不会得到Poly约束的类型推断(有关如何使该函数更好理解的任何想法) )。

但是,如果您只有一个或几个需要这种多态行为的函数,那么Poly不会让我感到困扰。 但是例如,您发现这个问题很多(我发现在单元测试中这个问题很多,这就是创建软件包的灵感),然后您可能会发现多数据很有用。

还有一个异类列表 ,我将其创建为多数据的扩展,它使您可以创建混合类型的列表,并以一种类型安全的方式映射它们。 您可能会发现有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM