2013-04-20 22 views
18

Tôi là người mới làm quen với Haskell, vì vậy xin lỗi nếu câu trả lời là hiển nhiên, nhưng tôi đang làm việc thông qua Typeclassopedia trong nỗ lực hiểu rõ hơn về các danh mục. Khi làm các bài tập cho phần trên functors, tôi tình cờ gặp vấn đề này:Ví dụ về loại có loại * -> * không thể là trường hợp của Functor

Hãy cho một ví dụ về một loại loại * -> * mà không thể được thực hiện một thể hiện của functor (không sử dụng không xác định).

Suy nghĩ đầu tiên của tôi là xác định một số loại định nghĩa vô hạn đệ quy của fmap, nhưng về cơ bản sẽ không giống như nếu undefined được sử dụng trong định nghĩa?

Nếu ai đó có thể giải thích câu trả lời, nó sẽ được đánh giá cao.

Cảm ơn!

Nguồn tập thể dục ban đầu ở đây, phần 3: http://www.haskell.org/haskellwiki/Typeclassopedia#Introduction

+1

Điều gì về '(-> int)'? –

+1

@RamonSnir '((->) Int)' thực sự là tốt, bạn cần một cái gì đó như 'dữ liệu K a = K (a -> Int)'. –

+0

@MikhailGlushenkov, gần như chắc chắn ý nghĩa của Ramon, giống như '(+ 1) = \ a -> a + 1'. – huon

Trả lời

22

Một ví dụ đơn giản là

data K a = K (a -> Int) 

Đây là những gì ghci cho chúng ta biết được chúng tôi cố gắng để tự động lấy một ví dụ Functor cho K:

Prelude> :set -XDeriveFunctor 
Prelude> data K a = K (a -> Int) 
Prelude> :k K 
K :: * -> * 
Prelude> data K a = K (a -> Int) deriving Functor 

<interactive>:14:34: 
    Can't make a derived instance of `Functor K': 
     Constructor `K' must not use the type variable in a function argument 
    In the data type declaration for `K' 

Vấn đề là tiêu chuẩn Functor lớp thực sự đại diện cho covariant functors (fmap nâng đối số của nó lên f a -> f b), nhưng không có cách nào bạn có thể soạn a -> ba -> Int để có được chức năng loại b -> Int (xem câu trả lời của Ramon). Tuy nhiên, nó có thể định nghĩa một lớp kiểu cho functors contravariant:

class Contravariant f where 
    contramap :: (a -> b) -> f b -> f a 

và làm K một thể hiện của nó:

instance Contravariant K where 
    contramap f (K g) = K (g . f) 

Để biết thêm về hiệp phương sai/contravariance trong Haskell, xem here.

Chỉnh sửa: Đây cũng là a nice comment on this topic từ Chris Smith trên Reddit.

+1

+1 cho 'CoFunctor's. –

+0

Cảm ơn, vì vậy nếu tôi hiểu chính xác, vấn đề là đối với định nghĩa fmap cho K, chúng tôi có '(a -> b) -> K (a -> Int) -> K (a -> b)' được xác định bằng cách cố gắng soạn một hàm của kiểu 'a -> Int' và một hàm kiểu' a -> b', không hoạt động vì kiểu 'a' sẽ phải được sửa thành' Int'? –

+4

@JS Bạn có một chức năng của kiểu 'a -> b' và một hàm của kiểu' a -> Int', và bạn phải tạo một hàm kiểu 'b -> Int'. Nhưng không có cách nào bạn có thể soạn các đầu vào để có được kết quả mong muốn. –

6

Để mở rộng (viết tắt) của tôi bình luận và trên Mikhail của câu trả lời:

Với (-> Int), bạn mong muốn fmap nhìn như vậy:

(a -> Int) -> (a -> b) -> (b -> Int) 

hay:

(a -> Int) -> (a -> b) -> b -> Int 

Thật dễ dàng để chứng minh rằng từ ba đối số (a -> Int), (a -> b), b không có cách nào để đạt được Int (không có undefined), do đó từ (a -> Int), (a -> b) không có cách nào để đạt được (b -> Int). Kết luận: không có Functor phiên bản tồn tại cho (-> Int).

+2

Bằng chứng đơn giản: Chúng tôi có hai định lý, cả hai đều yêu cầu bằng chứng cho 'a'. Chúng tôi chỉ có bằng chứng cho 'b'. Không có chứng cứ mới nào có thể được bắt nguồn (vì không có định lý nào được áp dụng) => không có chứng cứ nào có thể được bắt nguồn cho 'Int'. –

Các vấn đề liên quan