2015-10-14 20 views
6

Tôi có một loại (gọi nó là A) và tôi muốn tạo một kiểu chữ của các hàm kiểu A -> A, A -> A -> A, A -> A -> A -> ... vv Điều này không làm việc:Haskell - Tất cả các chức năng của mẫu A -> A -> ... -> A

{-# LANGUAGE FlexibleInstances #-} 

data A = A 

class AsToA a where 
    takeA :: AsToA b => a -> A -> Either A b 

instance AsToA (A -> A) where 
    takeA f a = Left (f a) 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

tôi nhận được thông báo lỗi sau:

AsToA.hs:12:22: 
    Couldn't match expected type ‘b1’ with actual type ‘b’ 
     ‘b’ is a rigid type variable bound by 
      the instance declaration at AsToA.hs:11:10 
     ‘b1’ is a rigid type variable bound by 
      the type signature for 

      takeA :: AsToA b1 => (A -> b) -> A -> Either A b1 
      at AsToA.hs:12:3 
    Relevant bindings include 
     f :: A -> b (bound at AsToA.hs:12:9) 
     takeA :: (A -> b) -> A -> Either A b1 (bound at AsToA.hs:12:3) 
    In the first argument of ‘Right’, namely ‘(f a)’ 
    In the expression: Right (f a) 

Bất kỳ ý tưởng? Cảm ơn rất nhiều vì lời khuyên nào.

+0

Tôi chắc chắn 90% đó là vì 'takeA' được định lượng tiềm ẩn hoàn toàn. –

Trả lời

2

Như đã đề cập trong các ý kiến ​​để câu trả lời khác, bạn có thể không thực sự cần Either, và takeA là sau đó về cơ bản luôn id, chỉ với một hạn chế loại. Nếu vậy bạn có thể làm điều này một phương pháp ít lớp:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-} 

data A = A 

class AsToA a 

takeA :: AsToA a => a -> a 
takeA = id 

instance AsToA (A -> A) 

instance AsToA (A -> b) => AsToA (A -> (A -> b)) 

Ngoài ra, bạn có thể muốn chuyển đổi các chức năng để một loại phổ biến cho phép bạn vượt qua trong A s động.Nếu vậy Either sẽ không đủ, nhưng bạn có thể xác định của riêng bạn:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-} 

data A = A 

data R = Result A | MoreArgs (A -> R) 

class AsToA a where 
    takeA :: a -> A -> R 

instance AsToA (A -> A) where 
    takeA f a = Result (f a) 

instance AsToA (A -> b) => AsToA (A -> (A -> b)) where 
    takeA f a = MoreArgs (takeA $ f a) 
+0

Câu trả lời thứ hai là hoàn hảo, cảm ơn rất nhiều. Tôi xin lỗi nếu trước đây tôi không rõ lắm. – RhubarbAndC

4

Có một số nhầm lẫn giữa hai b s:

class AsToA a where 
    takeA :: AsToA b => a -> A -> Either A b 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

Đây là không giống nhau. Hãy đổi tên người đầu tiên c

class AsToA a where 
    takeA :: AsToA c => a -> A -> Either A c 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

Bây giờ, Right (f a) đã gõ Either A b nhưng cần phải có loại Either A c cho bất kỳ cAsToA c giữ. Điều này không loại kiểm tra.

Vấn đề ở đây là chữ ký

takeA :: AsToA c => a -> A -> Either A c 

lời hứa rằng takeA có thể trở lại Either A c cho bất kỳc, người gọi lựa chọn. Đây không phải là những gì bạn muốn, tôi đoán.


Tôi vẫn không chắc chắn về kết quả dự định thực tế là gì, nhưng tôi đoán vấn đề tương tự như sau.

Với một hàm f loại A->A->...->A trả về một hàm \x -> f x x ..., với một ứng dụng của x cho mỗi -> trong các loại (do đó loại A->A).

Một giải pháp khả thi là

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-} 
data A = A -- could be anything 

class C f where 
    takeA :: f -> A -> A 

instance C (A -> A) where 
    takeA f = f 

instance C b => C (A -> b) where 
    takeA f = \x -> takeA (f x) x 

Lưu ý rằng điều này đòi hỏi OverlappingInstances được sử dụng, đó là khá ác. Tôi khuyên bạn nên tránh nó.

Để tránh điều này, trong trường hợp này là đủ để xác định một cá thể ngay cả đối với loại A.

{-# LANGUAGE FlexibleInstances #-} 
data A = A -- could be anything 

class C f where 
    takeA :: f -> A -> A 

instance C A where 
    takeA a = \_ -> a 

instance C b => C (A -> b) where 
    takeA f = \x -> takeA (f x) x 
+1

* hứa rằng takeA có thể trả về A hoặc C cho bất kỳ c * - về cơ bản, đó là vấn đề 'takeA' được khai báo là' forall b. AsToA b = a -> a -> Hoặc A b', trong đó 'b' trong cá thể là cứng nhắc, phải không? –

+0

Vậy bạn đề nghị tôi làm gì? Có thể định nghĩa kiểu chữ này không? – RhubarbAndC

+1

@RhubarbAndC Tôi không chắc bạn cần gì 'Hoặc là 'cho –

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