tôi thực hiện đầu dò trong Haskell như sau:Transducers trong Haskell và những hạn chế monomorphism
{-# LANGUAGE RankNTypes #-}
import Prelude hiding (foldr)
import Data.Foldable
type Reducer b a = a -> b -> b
type Transducer a b = forall t. Reducer t b -> Reducer t a
class Foldable c => Collection c where
insert :: a -> c a -> c a
empty :: c a
reduce :: Collection c => Transducer a b -> c a -> c b
reduce f = foldr (f insert) empty
mapping :: (a -> b) -> Transducer a b
mapping f g x = g (f x)
Bây giờ tôi muốn xác định một map
hàm tổng quát. Do đó tôi tải mã trên vào GHCi:
Prelude> :load Transducer
[1 of 1] Compiling Main (Transducer.hs, interpreted)
Ok, modules loaded: Main.
*Main> let map = reduce . mapping
<interactive>:3:20:
Couldn't match type ‘Reducer t0 b1 -> Reducer t0 a1’
with ‘forall t. Reducer t b -> Reducer t a’
Expected type: (a1 -> b1) -> Transducer a b
Actual type: (a1 -> b1) -> Reducer t0 b1 -> Reducer t0 a1
Relevant bindings include
map :: (a1 -> b1) -> c a -> c b (bound at <interactive>:3:5)
In the second argument of ‘(.)’, namely ‘mapping’
In the expression: reduce . mapping
*Main> let map f = reduce (mapping f)
*Main> :t map
map :: Collection c => (a -> b) -> c a -> c b
Vì vậy, tôi không thể xác định map = reduce . mapping
. Tuy nhiên, tôi có thể xác định map f = reduce (mapping f)
.
Tôi tin rằng vấn đề này là do hạn chế monomorphism. Tôi thực sự muốn viết map = reduce . mapping
thay vì map f = reduce (mapping f)
. Do đó, tôi có hai câu hỏi:
- Điều gì gây ra sự cố này? Nó thực sự là hạn chế monomorphism?
- Làm cách nào để khắc phục sự cố này?
Điều này là do suy luận kiểu với xếp hạng cao hơn. Hạn chế monomorphism không quan trọng ở đây. Không có cách khắc phục dễ dàng, tôi đoán, ngoại trừ việc thêm chú thích kiểu hoặc chuyển sang định nghĩa chính xác. – chi
Chú thích loại không giúp: 'cho phép bản đồ :: Bộ sưu tập c => (a -> b) -> c a -> c b; map f = reduce (ánh xạ f) 'vẫn tạo ra lỗi tương tự. –
Lỗi loại cho bạn biết chính xác vấn đề là gì. Kiểu 'ánh xạ' được âm thầm thay đổi để di chuyển' forall' sang bên trái (thử ': t mapping'). Đây là một phép biến đổi hợp lý (bảo tồn ngữ nghĩa), nhưng trình gõ nhãn mong đợi kiểu «Đầu dò a b' đúng, không phải' Giảm tốc t a -> Giảm tốc t b' (mà * có thể * là các kiểu riêng biệt). Nhưng khi bạn viết 'reduce (mapping f)', typechecker thấy ứng dụng 'mapping f' phải có kiểu' forall t. Reducer t b -> Reducer t a', là kiểu đúng cho đối số 'reduce'. – user2407038