とりあえず叩き台としてコード書いてみたよ。

tailFile n h = do
 seekable <- hIsSeekable h
 if seekable
  then do
   sz <- hFileSize h
   hSeek h AbsoluteSeek $ max 0 (sz - n)
   hGetContents h
  else do
   takeLast n <$> hGetContents h

takeLast n xs = diff xs (genericDrop n xs) where
 diff xs [] = xs
 diff (_:xs) (_:ys) = diff xs ys