Hãy bắt đầu bằng một ngôn ngữ tổng thể như Agda. Sau đó, như gallais tuyên bố, điều này chỉ có ý nghĩa nếu theo "loại trống", bạn có nghĩa là loại đơn vị, tức là bộ dữ liệu 0-ary, có chính xác một giá trị. Loại trống có thể được coi là loại tổng 0 trường hợp và không có giá trị nào cả. Trong Agda, bạn có thể dễ dàng chứng minh rằng nó Unit -> Alà đẳng cấu A. Theo nghĩa đó, bạn có thể coi chúng giống nhau, mặc dù chúng vẫn không giống nhau theo nghĩa đen. Tôi không thể, ví dụ, làm một phân tích trường hợp trên Unit -> Boolvà tôi cũng không thể áp dụng True : Boolcho bất cứ điều gì như là một chức năng.
Câu chuyện cho Haskell khá khác biệt. () -> Avà Alà các loại không đẳng cấu. Đặc biệt, () -> ()có bốn giá trị, trong khi ()chỉ có 2. Bốn observationally biệt giá trị undefined, \_ -> undefined, \x -> x, \_ -> (). Vì vậy, ()thực sự không phải là một loại đơn vị, theo nghĩa là có chính xác một chức năng (). (Trong Agda, mặt khác, chúng ta có thể chứng minh rằng nếu x : Unitvà y : Unit, thì chúng bằng nhau [theo định nghĩa vì vậy nếu chúng ta xác định Unitbằng recordcú pháp trái ngược với datacú pháp]. Điều đó có nghĩa là, Unitchỉ có một giá trị. Unitvà A -> Unitlà đẳng cấu cho bất kỳ A.)
Trong thực tế, một loại "trống" như Voidđược định nghĩa data Voidgần giống như một loại đơn vị theo nghĩa này. Voidchỉ có một giá trị, nhưng Void -> Voidvẫn có hai. Trong thực tế, mọi loại hàm A -> B, có ít nhất hai giá trị riêng biệt quan sát được, đó là undefinedvà \_ -> undefined. Do đó, Haskell không có đơn vị thực sự hoặc loại khoảng trống.
Rất nhiều điều này là do Haskell là một ngôn ngữ không nghiêm ngặt và bị bực tức bởi sự tồn tại của seq(và tương đương của nó). Ví dụ, sự khác biệt giữa undefinedvà \_ -> undefinedchỉ có thể được nhìn thấy với seq. Nếu chúng ta loại bỏ seqvà tương đương với Haskell, thì Voidsẽ phục vụ như một loại đơn vị, tuy nhiên, trớ trêu thay, vẫn không phải là một loại trống.
Thông thường, khi mọi người nói về những điều như vậy trong Haskell, họ ngầm giả vờ rằng Haskell là một ngôn ngữ cư xử tốt hơn nó. Đó là, họ cho rằng đáy không tồn tại cho mục đích của họ, tức là bạn đang làm việc trong một ngôn ngữ tổng thể như Agda. Đối với mục đích thiết kế mã của bạn, điều này thường là đầy đủ; nó không phổ biến mà chúng ta quan tâm hoặc mong đợi đáy. Những khác biệt này có thể trở nên quan trọng nếu chúng ta đang làm một cái gì đó như lập trình vòng tròn hoặc nếu đảm bảo an toàn cho chương trình của chúng tôi dựa vào các thuộc tính này, ví dụ: một hàm không bao giờ có thể được gọi nếu nó có kiểu trống như miền của nó.