在 Haskell 中研究多变量函数时,我偶然发现了以下 SO 问题:
并认为我会通过实现一个函数来尝试它,该函数接受可变数量的字符串并将它们连接/合并成一个字符串:
{-# LANGUAGE FlexibleInstances #-}
class MergeStrings r where
merge :: String -> r
instance MergeStrings String where
merge = id
instance (MergeStrings r) => MergeStrings (String -> r) where
merge acc = merge . (acc ++)
如果我用至少一个字符串参数调用合并并且我提供最终类型,这到目前为止有效。
foo :: String
foo = merge "a" "b" "c"
省略最终类型会导致错误,即编译如下
bar = merge "a" "b" "c"
结果是
test.hs:12:7: error:
• Ambiguous type variable ‘t0’ arising from a use of ‘merge’
prevents the constraint ‘(MergeStrings t0)’ from being solved.
Relevant bindings include bar :: t0 (bound at test.hs:12:1)
Probable fix: use a type annotation to specify what ‘t0’ should be.
These potential instances exist:
instance MergeStrings r => MergeStrings (String -> r)
-- Defined at test.hs:6:10
instance MergeStrings String -- Defined at test.hs:4:10
• In the expression: merge "a" "b" "c"
In an equation for ‘bar’: bar = merge "a" "b" "c"
|
12 | bar = merge "a" "b" "c"
|
错误消息非常有意义,因为我可以很容易地想出,例如
bar :: String -> String
bar = merge "a" "b" "c"
baz = bar "d"
不是渲染bar
成单个字符串,而是渲染成一个接受并返回一个字符串的函数。
有没有办法告诉 Haskell 结果类型必须是 type String
?例如,在没有明确定义的情况下Text.Printf.printf "hello world"
计算类型。String