2014-12-02 66 views
0

我已经在过去一次写入以下函数来将列表中的整数x的任何实例替换为另一个整数y。这里是我的代码:如何更改此函数以使用任何类型,而不仅仅是Int

substitute::Int->Int->[Int]->[Int] 
substitute x y []   =[] 
substitute x y (z:zs) 
    |(z==x)     =y:substitute x y (zs) 
    |otherwise    =z:substitute x y (zs) 

下面是一个示例调用:

main = do 
print $ substitute 2 3 [2, 2, 2] 

我现在想与任何类型的输入此代码的工作。所以我尝试将参数类型转换为通用的“a”,但是它会吐出一个错误,因为Haskell认为它是某种习惯的高阶函数。那么,如何使这项工作:找出

substitute::a->a->[a]->[a] 
substitute x y []   =[] 
substitute x y (z:zs) 
    |(z==x)     =y:substitute x y (zs) 
    |otherwise    =z:substitute x y (zs) 


main = do 
print $ substitute 2 'a' [2, 2, 2] 
+0

在您的下一个问题中,请始终发布错误。它通常会帮助读者,并提高你得到答案的机会。 – chi 2014-12-02 09:41:37

回答

2

的一种方法是从你的代码中删除类型签名,发现它使用ghci的:

λ> :t substitute 
substitute :: Eq a => a -> a -> [a] -> [a] 

Haskell有一个很好的类型推断,所以它会自动为您提供最多样化的类型。

substitute :: Eq a => a -> a -> [a] -> [a] 
substitute x y []   =[] 
substitute x y (z:zs) 
    |(z==x)     =y:substitute x y (zs) 
    |otherwise    =z:substitute x y (zs) 

UPDATE:刚才看到你更新的问题。 Haskell在默认情况下没有异构列表,所以你不想要做什么。但是你可以使用Existential数据类型来获得你想要的。阅读this section了解更多关于它。

{-# LANGUAGE ExistentialQuantification #-} 

data ShowBox = forall s. Show s => SB s 

instance Show ShowBox where 
    show (SB s) = show s 

substitute :: ShowBox -> ShowBox -> [ShowBox] -> [ShowBox] 
substitute x y []   =[] 
substitute (SB x) (SB y) ((SB z):zs) 
    |(show z == show x) = (SB y):substitute (SB x) (SB y) (zs) 
    |otherwise    = (SB z):substitute (SB x) (SB y) (zs) 

λ> substitute (SB 'a') (SB 3) [SB 1, SB 'a', SB 3] 
[1,3,3] 

请注意,上述程序是反模式。除非你有正确的理由,否则不要这样做。

+0

所以如何做这个编译:main = do print $ substitute 2“a”[2,2,2] – 2014-12-02 06:15:19

+0

@KannyBros更新了我的答案。 – Sibi 2014-12-02 06:38:21

0

Haskell支持多态性,因此可以创建类似于您需要的函数。 @Sibi的回应显示了找出它的一种方法,但并不能解释为什么,所以我会告诉你为什么。

很明显,你的函数的类型为a -> a -> [a] -> [a],如你所指出的,而是因为你使用==功能,属于Eq类型类,应用了约束:(Eq a) => a -> a -> [a] -> [a]。是的,这需要Haskell类型类的知识,但是当你没有GHCi的时候值得学习。

有时我们可以通过使用模式匹配来避免在我们的函数类型中使用典型的Eq,但不幸的是,我没有看到任何最新的方法来删除==并替换模式。也许在未来,Haskell将支持像plus a a = 2 * a这样的函数模式,但这是一厢情愿的想法。

理解多态类型签名的一个有用的注释是类似上述a的名称被称为类型变量。将它们与具体类型区分开的方式很简单:它们始终以小写字母开头,而类型类构造函数以大写字母或:开头,用于中缀构造函数,但函数中缀构造函数->除外。

相关问题