関数型宣言の追記&nlistToStringの一般化 (0〜9の数字を使って、掛け算して、Go!解けた。)
前出の
nlistToString nl = concatMap show nl
ですが、数値のリストを文字列にするために用意した関数でしたが、別に数値のリストじゃなくてもよいのでは?と思い、以下のようにしてみることに。
listToString :: [a] -> String listToString l = concatMap show l
が、大量(?)のコンパイルエラーが発生。
kake.hs:16:27: Could not deduce (Show a) from the context () arising from a use of `show' at kake.hs:16:27-30 Possible fix: add (Show a) to the context of the type signature for `listToString' In the first argument of `concatMap', namely `show' In the expression: concatMap show l In the definition of `listToString': listToString l = concatMap show l
なんのこっちゃと思ったらどうも、Java的に言えば、
String listToString(Object o)
{
concatMap(show(o));
}
String show(Showable s)
{
return s.toString();
}
という感じで、show関数はShowableな型を期待しているのに、listToString関数はshow関数に対してObject型(Haskell的には多相型)を渡してしまっているということのようです。
こんな風にするとうまくいきます。
listToString :: (Show a) => [a] -> String listToString l = concatMap show l
[a]はShow可能である(Showable)という制限を付けたってことですね。
最終的なソースはこうなりました。
import List main = putStr $ unlines $ map format $ filter test $ perm [0,1,2,3,5,6,7,8,9] perm :: [Int] -> [[Int]] perm [] = [[]] perm xs = concat [map (x:) $ perm (delete x xs) | x <- xs] test :: [Int] -> Bool test [a,b,c,d,e,f,g,h,i] = if (400 + a*10 + b) * (c*10 + d) == (e*10000 + f*1000 + g*100 + h*10 + i) then True else False format :: [Int] -> String format [a,b,c,d,e,f,g,h,i] = listToString [4,a,b] ++ " x " ++ listToString[c,d] ++ " = " ++ listToString [e,f,g,h,i] listToString :: (Show a) => [a] -> String listToString l = concatMap show l
permも多相型化できそう。