haskell多态性和列表 [英] haskell polymorphism and lists

查看:129
本文介绍了haskell多态性和列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下内容:

  class Shape a where 
draw a :: a - > IO()

data Rectangle = Rectangle Int Int

实例形状Rectangle其中
draw(Rectangle length width)= ...

数据Circle = Circle Int Int

实例形状Circle其中
绘制(Circle center radius)= ...

是否有任何方法可以定义形状列表,遍历列表并在每个形状上调用draw函数?下面的代码不会编译,因为列表元素不是全部相同的类型:

  shapes = [(Circle 5 10 ),(Circle 20,30),(Rectangle 10 15)] 

我知道我在想以OO方式并试图将其应用于Haskell,而这可能不是最好的方法。对于需要处理不同类型对象集合的程序,最好的Haskell方法是什么? 解决方案

如果你真的这么做需要做到这一点,然后使用存在

  { - #LANGUAGE GADTs# - } 


class IsShape a其中
draw :: a - > IO()

data Rectangle = Rectangle Int Int

实例IsShape Rectangle其中
draw(矩形长度宽度)= ...

数据Circle = Circle Int Int

实例IsShape Circle其中
绘制(圆心半径)= ...

数据形状其中
形状: :IsShape a => a - >形状

形状= [Shape(Circle 5 10),Shape(Circle 20 30),Shape(Rectangle 10 15)]

(我重命名了你的类,否则会有与数据类型相冲突的名称,并且以这种方式命名似乎更加自然)。



这个解决方案相对于包含具有不同构造函数的单个数据类型的其他答案的优点在于它打开;你可以在任何你喜欢的地方定义 IsShape 的新实例。其他答案的优点是它更功能性,而且在某些情况下,封闭性可能是一种优势,因为这意味着客户确切地知道期望的结果。


Suppose I have the following:

class Shape a where
    draw a :: a -> IO ()

data Rectangle = Rectangle Int Int

instance Shape Rectangle where
    draw (Rectangle length width) = ...

data Circle = Circle Int Int

instance Shape Circle where
    draw (Circle center radius) = ...

Is there any way for me to define a list of shapes, traverse over the list, and call the draw function on each shape? The following code won't compile because the list elements aren't all the same type:

shapes = [(Circle 5 10), (Circle 20, 30), (Rectangle 10 15)]

I know I'm thinking in an OO way and trying to apply it to Haskell, and that might not be the best approach. What would be the best Haskell approach for programs that need to deal with collections of different types of objects?

解决方案

If you really do need to do this, then use an existential:

{-# LANGUAGE GADTs #-}


class IsShape a where
    draw :: a -> IO ()

data Rectangle = Rectangle Int Int

instance IsShape Rectangle where
    draw (Rectangle length width) = ...

data Circle = Circle Int Int

instance IsShape Circle where
    draw (Circle center radius) = ...

data Shape where
    Shape :: IsShape a => a -> Shape

shapes = [Shape (Circle 5 10), Shape (Circle 20 30), Shape (Rectangle 10 15)]

(I renamed your class as there would be a name clash with the datatype otherwise, and having the naming this way round seems more natural).

The advantage of this solution over the other answer involving a single datatype with different constructors is that it is open; you can define new instances of IsShape wherever you like. The advantage of the other answer is that it's more "functional", and also that the closedness may in some cases be an advantage as it means that clients know exactly what to expect.

这篇关于haskell多态性和列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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