我有一个函数示例,其中我无法在 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)
当我尝试编译此函数时,出现错误:
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
同时,如果我省略
helper :: (Eq a) => a -> a
代码编译良好。
虽然我理解其背后的逻辑(replace
类型声明中的a
和helper
类型声明中的a
是不同的 a
),并且至少有 2 种解决方法(省略类型声明或将 x
和 y
作为参数传递给 helper
函数),我的问题是:
有什么方法可以告诉编译器我在两个类型声明中指的是相同的类型吗?
最佳答案
如果启用ScopedTypeVariables
并使用 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)
关于Haskell: `where` 中的类型声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29274751/