哈斯克尔。 “无法从上下文推导出(t~ [t])(Eq t)”

时间:2015-08-04 13:26:36

标签: haskell

亲自学习haskell,无法解决这个问题。这些是代码。

subst :: Eq t=>t->t->[t]->[t]
subst a b [xs]=[if x==a then b else x | x <- xs]

错误如下。

subst.hs:2:46:
    Could not deduce (t ~ [t])
    from the context (Eq t)
      bound by the type signature for
                 subst :: Eq t => t -> t -> [t] -> [t]
      at subst.hs:1:10-29
      ‘t’ is a rigid type variable bound by
          the type signature for subst :: Eq t => t -> t -> [t] -> [t]
          at subst.hs:1:10
    Relevant bindings include
      xs :: t (bound at subst.hs:2:12)
      b :: t (bound at subst.hs:2:9)
      a :: t (bound at subst.hs:2:7)
      subst :: t -> t -> [t] -> [t] (bound at subst.hs:2:1)
    In the expression: xs
    In a stmt of a list comprehension: x <- xs

问题,我想,haskell无法确保[t]中的元素与t匹配。我不确定。我想知道如何解决这个问题。

2 个答案:

答案 0 :(得分:6)

你只有一个[..]包装给许多人:

subst :: Eq t=>t->t->[t]->[t]
subst a b xs = [if x==a then b else x | x <- xs]

只是xs而不是[xs]

原因很简单:如果你写[xs],你告诉Haskell期望一个包含单个条目xs的列表,它会尝试模式匹配它 - 之后这告诉它从xxs)中提取值x <- xs,告诉Haskell xs必须是某种列表本身。所以最后它会假设t为某个列表t ~ [s]。但接下来,请继续检查x == a以及x :: sa :: t,以错误结束,现在为[s] ~ t ~ s

答案 1 :(得分:3)

在参数列表中编写[xs]。这是一个匹配包含一个元素的列表的模式,然后将其称为xs。这有两个后果:

  1. 这是一个非详尽的模式匹配,如果给定列表包含零个元素或多个元素,它将在运行时失败。由于您希望执行相同的代码,无论列表的长度如何,您都需要一个始终匹配的模式,例如xs没有括号。
  2. 由于xs中的[xs]引用了列表中的单个元素,因此其类型为t,而不是[t]。但是你使用它就好像它的类型是[t]一样,这导致Haskell断定t必须等于[t](在Haskell中使用~运算符来表示这两种类型是等于),这会导致你得到的有点混乱的类型错误。