nobsun です。

>    リストの最後のn個の要素を返す関数 tailn を素直に書けば
>    tailn n = reverse.(take n).reverse
> だと思うのですがこれは遅延評価であっても一度全リストをため
> こんでしまうんですよね。

reverse を使うと必ずそうなります。

> ためこまない tailn を次のように
> 書いてみたのですが
>
>    _tailn :: Int -> [a] -> [a] -> [a]
>    _tailn n hs [] = hs
>    _tailn 0 (_:hs) (_:ts) = _tailn 0 hs ts
>    _tailn n hs (t:ts) = _tailn (n-1) hs ts
> 
>    tailn :: Int -> [a] -> [a]
>    tailn n xs = _tailn n xs xs
> 
> 問題ないでしょうか。差分リストのつもりで書いたのですが

ちょいといじって、シンプルにすると

tailn :: Int -> [a] -> [a]
tailn n ls = difftail ls (drop n ls)
  where difftail hs []         = hs
        difftail (_:hs) (_:ts) = difftail hs ts

てな感じでしょうか。

> 「haskell 差分リスト」で検索してもどこのページも引っ掛からないので不安です。

このあたりのテクニックは、deforestation の範疇かな。

>    もしかして reverse と take を少し変更すれば素直っぽく
> それでいてためこまないように書けるのでしょうか。

reverse の意味から考えると、ためこまないというのはできないと思います。

--
Nobuo Yamashita                 mailto:nobsun / sampou.org
  I love programming.           http://www.sampou.org/
  I love pencil puzzles.        http://www.puzzle.jp/

--
ML: haskell-jp / quickml.com
使い方: http://QuickML.com/