第2回スタートHaskellの演習問題のsplitAtは自力で解けたのに、第3回スタートHaskellの演習問題では解けず時間切れになってくやしかったので、考えをメモりながら考えた。

ざくっと戦略はこう:

  • 基底部はこの形になるはず: splitAt 0 xs = ([],xs)
  • 再帰部は、タプルの1stを (:) でつくりつつ2ndはいじらない。

引数とおなじリストをつくる(リストコピー)はこの形↓なので、再帰部も同じ形になるはず。

copy [] = []
copy (x:xs) = x : copy xs

splitAtではタプルを返さないといけないから変形が必要で、「ひとつまえがあったら...」の考え方で、「splitAt n (x:xs)」は「(ys,zs) = splitAt (n-1) xs」をもとに「(x:ys, zs)」を返せばいいはず。

splitAt :: Int -> [a] -> ([a], [a])
splitAt n xs | n <= 0 = ([], xs)
splitAt _ [] = ([], [])
splitAt n (x:xs) = (x:ys, zs)
                   where
                   (ys, zs) = splitAt (n-1) xs

let式をつかうとこんなかんじ:

splitAt n (x:xs) | n > 0 = let (ys, zs) = splitAt (n-1) xs
                           in (x:ys, zs)
                 | otherwise = ([], (x:xs))
splitAt n [] = ([], [])

なんとか解けたので、ぐっすり寝れそうだ。