我来自C++,我发现泛型编程是不可或缺的。我想知道在Haskell中人们是如何做到这一点的?
说一下如何在Haskell中编写泛型交换函数?
在Haskell中是否存在部分专业化的等效概念?
在C++中,我可以使用一个特殊的通用map/hash_map容器的特殊函数来部分专门化通用的交换函数,该容器具有一个特殊的交换方法,用于O(1)容器交换。你如何在Haskell中做到这一点,或者在Haskell中泛型编程的规范示例是什么?
发布于 2008-12-18 08:01:28
这与你关于Haskell和quicksort的其他问题密切相关。我认为你可能至少需要阅读一本关于Haskell的书的介绍。听起来你似乎还没有抓住它的关键点,那就是它禁止你修改现有变量的值。
交换(在C++中理解和使用)本质上就是修改现有值。因此,我们可以使用名称来引用容器,并用完全不同内容替换该容器,并为特定的容器指定快速(和无异常)的操作,从而允许我们实现修改并发布方法(对于编写异常安全的代码或尝试编写无锁的代码至关重要)。
您可以在Haskell中编写通用交换,但它可能需要一对值,并返回包含相同值且位置颠倒的新对,或者类似的东西。其实不是一回事,用途也不一样。试图通过挖掘映射并交换其单个成员变量来将其专门化是没有任何意义的,因为在Haskell中不允许这样做(您可以进行专门化,但不能修改变量)。
假设我们想在Haskell中“测量”一个列表:
measure :: [a] -> Integer这是一个类型声明。这意味着函数measure接受一个包含所有内容的列表(a是一个泛型类型参数,因为它以小写字母开头)并返回一个整数。因此,这适用于任何元素类型的列表--在C++中称为函数模板,在Haskell中称为多态函数(与C++中的多态类不同)。
我们现在可以通过为每个有趣的案例提供专门化来定义它:
measure [] = 0例如,测量空列表,结果为零。
这里有一个非常通用的定义,涵盖了所有其他情况:
measure (h:r) = 1 + measure rLHS上括号中的位是一种模式。它的意思是:取一个列表,取下头部并将其命名为h,将剩余的部分命名为r。这些名称就是我们可以使用的参数。这将匹配任何至少包含一项的列表。
如果你在C++中尝试过模板元编程,你会觉得这一切都是老生常谈了,因为它涉及到了完全相同的风格--递归来做循环,专门化来终止递归。除了在Haskell中,它在运行时工作(针对特定值或值模式的函数的专门化)。
发布于 2008-12-18 08:28:07
正如Earwicker所说,这个例子在Haskell中没有意义。如果你真的想拥有它,这里有一些类似的东西(交换一对中的两个部分),来自交互式会话的c&p:
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help
Loading package base ... linking ... done.
Prelude> let swap (a,b) = (b,a)
Prelude> swap("hello", "world")
("world","hello")
Prelude> swap(1,2)
(2,1)
Prelude> swap("hello",2)
(2,"hello")发布于 2008-12-19 23:21:24
在Haskell中,函数尽可能的是泛型(多态)--编译器会推断出“最通用的类型”。例如,在没有类型签名的情况下,TheMarko的示例交换默认情况下是多态的:
*Main>令交换(a,b) = (b,a)
*Main> :t交换
交换::(t,t1) -> (t1,t)
至于部分专门化,ghc有一个非98扩展:
file:///C:/ghc/ghc-6.10.1/doc/users_guide/pragmas.html#specialize-pragma
此外,请注意,术语中存在不匹配。在c++、Java和C#中称为泛型的东西在Haskell中称为多态。"Generic“在Haskell中通常意味着多型性:http://haskell.readscheme.org/generic.html
但是,在上面我使用了泛型的c++含义。
https://stackoverflow.com/questions/377093
复制相似问题