Haskell:在`where`中键入声明

Mar*_*ova 5 haskell types

我有一个函数的例子,其中我不能写一个类型in where子句.replace是一个函数,它将给定列表中的所有X替换为Y.

replace :: (Eq a) => a -> a -> [a] -> [a]
replace x y xs = map helper xs
  where
    helper :: (Eq a) => a -> a
    helper = (\el -> if el == x then y else el)
Run Code Online (Sandbox Code Playgroud)

当我尝试编译此函数时,我收到一个错误:

ProblemsArithmetics.hs:156:31:
Could not deduce (a ~ a1)
from the context (Eq a)
  bound by the type signature for
             replace :: Eq a => a -> a -> [a] -> [a]
  at ProblemsArithmetics.hs:152:12-41
or from (Eq a1)
  bound by the type signature for helper :: Eq a1 => a1 -> a1
  at ProblemsArithmetics.hs:155:15-30
  ‘a’ is a rigid type variable bound by
      the type signature for replace :: Eq a => a -> a -> [a] -> [a]
      at ProblemsArithmetics.hs:152:12
  ‘a1’ is a rigid type variable bound by
       the type signature for helper :: Eq a1 => a1 -> a1
       at ProblemsArithmetics.hs:155:15
Relevant bindings include
  el :: a1 (bound at ProblemsArithmetics.hs:156:16)
  helper :: a1 -> a1 (bound at ProblemsArithmetics.hs:156:5)
  xs :: [a] (bound at ProblemsArithmetics.hs:153:13)
  y :: a (bound at ProblemsArithmetics.hs:153:11)
  x :: a (bound at ProblemsArithmetics.hs:153:9)
  replace :: a -> a -> [a] -> [a]
    (bound at ProblemsArithmetics.hs:153:1)
In the second argument of ‘(==)’, namely ‘x’
In the expression: el == x
Run Code Online (Sandbox Code Playgroud)

同时,如果我省略

helper :: (Eq a) => a -> a
Run Code Online (Sandbox Code Playgroud)

代码编译得很好.

虽然我理解其背后的逻辑(areplace类型声明和ahelper类型声明是不同的aS),并有至少2个解决方法(省略类型声明或通过xy作为参数helper的作用),我的问题是:

有没有办法告诉编译器我的意思是两种类型声明中的相同类型?

And*_*ács 10

如果启用ScopedTypeVariables并引入带有a的类型变量forall,则它在内部作用域中变为可见.

{-# LANGUAGE ScopedTypeVariables #-}

replace :: forall a. (Eq a) => a -> a -> [a] -> [a]
replace x y xs = map helper xs
  where
    helper :: a -> a
    helper = (\el -> if el == x then y else el)
Run Code Online (Sandbox Code Playgroud)