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 ++)
これは、少なくとも 1 つの文字列引数を指定して merge を呼び出し、最終型を指定すると、これまでのところ機能します。
foo :: String
foo = merge "a" "b" "c"
final 型を省略すると、エラーが発生します。つまり、次をコンパイルします。
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
の文字列ではなく、1 つの文字列を受け取って返す関数に変換します。
結果の型が型でなければならないことを Haskell に伝える方法はありString
ますか? たとえば、明示的に定義せずText.Printf.printf "hello world"
に型に評価されます。String