我想将子数据类型传递给函数。
一个例子:
data Car a = Ford | Opel | BMW | Mercedes a deriving (Show)
data Mercedes a = SClass a| CClass a| MClass a
myfunc::Car->String
myfunc a = show a ++ " works correctly"
但我这样做:
myfunc CClass“x”
它说
不在范围内:构造函数CClass
答案 0 :(得分:11)
要实现" sub" -types,可以选择一些。第一种是在您尝试使用更多data
类型时使用:
data Car a = Ford (Ford a) | Mercedes (Mercedes a) deriving (Show)
data Ford a = ModelT a | Falcon a deriving (Show) -- different Fords models
data Mercedes a = CClass a | SClass a deriving (Show) -- different Mercedes models
请注意,作为一个类型构造函数不同于作为数据构造函数,所以不能只使用data Car = .. | Mercedes a
:这就是说Car String
的一种方法就是通过说Mercedes "a"
,它与名为Mercedes
的类型无关。现在可以使用如下函数:
horsepower :: Car a -> Float
horsepower (Ford (ModelT _)) = 1
horsepower (Ford (Falcon _)) = 500
horsepower (Mercedes (CClass _)) = 300
horsepower (Mercedes (SClass _)) = 400
你的例子是:
myfunc :: Show a => Car a -> String
myfunc a = show a ++ " works correctly"
-- myfunc (Ford (ModelT "A")) => Ford (ModelT "A") works correctly
-- myfunc (Mercedes (CClass "b")) => Mercedes (CClass "b") works correctly
允许"子类型化的另一种方式"像这样是使用类型类(取决于具体情况,这可能是一个更好的选择)。 E.g。
class (Show c) => Car c where
make :: String
model :: c -> String
horsepower :: c -> Float
number_of_seats :: c -> Int
-- etc.
data Ford a = ModelT a | Falcon a deriving (Show)
instance (Show a) => Car (Ford a) where
make = "Ford"
horsepower (ModelT _) = 1
horsepower (Falcon _) = 500
-- etc.
data Mercedes a = CClass a | SClass a deriving (Show)
instance (Show a) => Car (Mercedes a) where
make = "Mercedes"
horsepower (CClass _) = 300
horsepower (SClass _) = 400
-- etc.
myfunc
的例子可能是:
myfunc :: (Car c) => c -> String
myfunc c = (make `asTypeOf` c) ++ " " ++ show c ++ " works correctly"
-- myfunc (ModelT "A") => Ford ModelT "A" works correctly
-- myfunc (CClass "b") => Mercedes CClass "b" works correctly
另请注意,必须使用括号调用function (Ford (Ford "a"))
(或function (CClass "a")
)等函数。
答案 1 :(得分:5)
首先,您需要按如下方式定义您的汽车类型:
data Car a = ... | Mercedes (MercedesClass a) | ...
data MercedesClass a = CClass a | ...
...然后你可以写:
myFunc (Mercedes (CClass "x"))