Nếu bạn tạo một hàm so sánh rằng dấu vết đối số của nó, như thế này trong dòng lệnh GHCi của:
> :module + Data.List Debug.Trace
> let myCompare x y = trace ("\tCmp " ++ show x ++ " " ++ show y) $ compare x y
sau đó bạn sẽ nhìn thấy hành vi của mình:
> sortBy myCompare "foobar"
" Cmp 'f' 'o'
Cmp 'o' 'b'
Cmp 'f' 'b'
Cmp 'a' 'r'
Cmp 'b' 'a'
a Cmp 'b' 'r'
b Cmp 'f' 'o'
Cmp 'f' 'r'
f Cmp 'o' 'o'
Cmp 'o' 'r'
o Cmp 'o' 'r'
or"
Haskell đang đánh giá chuỗi uể oải , một nhân vật tại một thời điểm. Cột bên tay trái đang được in dưới dạng mỗi ký tự được tìm thấy, với cột bên tay phải ghi các so sánh cần thiết, như được in bằng "dấu vết".
Lưu ý rằng nếu bạn biên dịch điều này, đặc biệt là khi tối ưu hóa, bạn có thể nhận được kết quả khác. Trình tối ưu hóa chạy một máy phân tích nghiêm ngặt có thể sẽ nhận thấy rằng toàn bộ chuỗi được in, vì vậy sẽ hiệu quả hơn khi đánh giá nó một cách háo hức.
Sau đó thử
> head $ sortBy myCompare "foobar"
Cmp 'f' 'o'
Cmp 'o' 'b'
Cmp 'f' 'b'
Cmp 'a' 'r'
Cmp 'b' 'a'
'a'
Nếu bạn muốn hiểu cách làm việc này, tìm kiếm các mã nguồn cho các chức năng sắp xếp và đánh giá 'sắp xếp 'foobar'' bằng tay trên giấy.
qsort [] = []
qsort (x:xs) = qsort less ++ [x] ++ qsort greater
where (less, greater) = partition (< x) xs
Vì vậy
qsort ('f':"oobar")
= qsort ('b':"a") ++ "f" ++ qsort ('o':"or")
= ("a" ++ "b") ++ "f" ++ qsort ('o':"or")
Và bây giờ chúng ta đã làm đủ để thấy rằng 'a' là mục đầu tiên trong kết quả mà không cần phải đánh giá các cuộc gọi khác đến "qsort". Tôi đã bỏ qua sự so sánh thực tế bởi vì nó ẩn bên trong cuộc gọi đến "phân vùng". Trên thực tế "phân vùng" cũng là lười biếng, do đó, trong thực tế, các đối số khác "qsort" đã không được đánh giá như xa như tôi đã hiển thị nó.
Phần cuối cùng này không chính xác; trình biên dịch không thể suy ra ý định! – porges
Porges: Trong khi trình biên dịch có thể được hardwired để phân tích ý định trong trường hợp cụ thể, bạn không ** cần ** suy luận * ý định *. Bạn cần sử dụng một định lý cơ học để chứng minh rằng phiên bản được tối ưu hóa của mã là toán học tương đương với phiên bản gốc. Ngôn ngữ chức năng làm cho định lý này chứng minh dễ dàng hơn bằng cách không cho phép tác dụng phụ. –
Có thể, nhưng tôi không biết của bất kỳ trình biên dịch Haskell hơn bao gồm provers định lý tự động như là một phần của vượt qua tối ưu hóa của họ. Lý do thành phần các chức năng này hoạt động chỉ vì tính chất mặc định lười của Haskell. – porges