Tính năng mở rộng cho biểu thức danh sách trong Haskell

Mở rộng biểu thức danh sách (List Comprehensions)

Haskell cung cấp một số phần mở rộng ngôn ngữ để tăng cường khả năng của biểu thức danh sách, giúp viết mã ngắn gọn và gần với truy vấn SQL.

ParallelListComp

Phần mở rộng ParallelListComp cho phép kết hợp các luồng sinh giá trị song song bằng cách sử dụng ký hiệu | thay vì lồng nhau. Điều này tương đương với việc dùng zip giữa các danh sách được tạo độc lập.
Prelude> :set -XParallelListComp
Prelude> [(a,b,c,d) | a <- [1..3], b <- [2..4] | c <- [3..5], d <- [4..6]]
[(1,2,3,4),(1,3,3,5),(1,4,3,6),(2,2,4,4),(2,3,4,5),(2,4,4,6),(3,2,5,4),(3,3,5,5),(3,4,5,6)]
Mỗi cặp biến ở hai phía của dấu | được ghép theo vị trí, giống như hành vi của zip.

TransformListComp

Phần mở rộng TransformListComp bổ sung cú pháp mới vào biểu thức danh sách: then, group, by, và using. Nhờ đó, người dùng có thể áp dụng các phép biến đổi như sắp xếp hoặc nhóm phần tử ngay trong biểu thức.
Prelude> :set -XTransformListComp
Prelude> :m +GHC.Exts
Prelude GHC.Exts> [(i,j) | i <- [1..3], j <- [2..4], then reverse]
[(3,4),(3,3),(3,2),(2,4),(2,3),(2,2),(1,4),(1,3),(1,2)]

Prelude GHC.Exts> [(i,j) | i <- [1..3], j <- [2..4], then sortWith by (i+j)]
[(1,2),(1,3),(2,2),(1,4),(2,3),(3,2),(2,4),(3,3),(3,4)]

Prelude GHC.Exts> [(sum vals, vals) | i <- [1..3], j <- [2..4], let vals = [(i,j)], then group by (i+j) using groupWith]
[(3,[(1,2)]),(4,[(1,3),(2,2)]),(5,[(1,4),(2,3),(3,2)]),(6,[(2,4),(3,3)]),(7,[(3,4)])]
Cú pháp then f by e cho phép chỉ định hàm biến đổi f và khóa e để sắp xếp hoặc nhóm. Hàm groupWith từ GHC.Exts thường được dùng cùng với group by ... using. Ví dụ khác sử dụng inits từ Data.List:
Prelude GHC.Exts Data.List> [x | x <- [1..3], then group using inits]
[[],[1],[1,2],[1,2,3]]

MonadComprehensions

Khi bật cả MonadComprehensionsTransformListComp, biểu thức danh sách có thể hoạt động trên bất kỳ monad nào, không chỉ là danh sách. Điều này cho phép viết các biểu thức kiểu danh sách trong ngữ cảnh Maybe, IO, v.v.
{-# LANGUAGE MonadComprehensions, TransformListComp #-}

pairs :: [(String, Int)]
pairs = [("a", 1), ("b", 2), ("c", 3)]

example = [ (x, y)
          | x <- lookup "a" pairs
          , y <- lookup "b" pairs
          , then (\f -> case f of
                         v | v == 2 -> Just (x, y)
                         _         -> Nothing)
                by (x * y)
          ]
-- Kết quả: Just (1,2)
Trong ví dụ trên, lookup trả về Maybe Int, và toàn bộ biểu thức được đánh giá trong ngữ cảnh monad Maybe. Phần mở rộng then ... by vẫn hoạt động nhờ hỗ trợ từ TransformListComp.

Thẻ: Haskell ListComprehensions ParallelListComp TransformListComp MonadComprehensions

Đăng vào ngày 30 tháng 5 lúc 18:13