let 式

プログラミング Haskell 第8章 関数型パーサーに使われている string 関数について訳者が解説していて、その中に let ... in ...という表現が出てきました。使ったことがないので調べてみました。

-- let
sum2 :: (Num a) => [a] -> a
sum2 xs = let sum' []     work = work
              sum' (y:ys) work = sum' ys (y + work)
          in  sum' xs 0

sum3 :: (Num a) => [a] -> a
sum3 []     = 0
sum3 (x:xs) = x + (sum3 xs)
ghci> sum2 [1,2,3]
6
ghci> sum3 [1,2,3]
6
import Debug.Trace

-- let
unzip1 :: [(a, b)] -> ([a], [b])
unzip1 [] = ([], [])
unzip1 ((a, b):rest) = let (as, bs) = unzip1 rest 
                       in (a:as, b:bs)      
-- where
unzip2 :: (Show a, Show a1) => [(a, a1)] -> ([a], [a1])
unzip2 []         = trace("([], [])")([], [])
unzip2 ((a,b):xs) = trace(show (a:as, b:bs)) (a:as, b:bs)
                    where
                      (as, bs) = trace("unzip2 "++show xs)(unzip2 xs)
ghci>  unzip2 [(1,2),(3,4),(5,6)]
unzip2 [(3,4),(5,6)]
unzip2 [(5,6)]
unzip2 []
([], [])
(5:[],6:[])
(3:[5],4:[6])
(1:[3,5],2:[4,6])
([1,3,5],[2,4,6])

Let vs. Where