2016-09-22 18 views
5

Tôi đã chơi với một số phần mở rộng GHC để xác định một chức năng có thể làm như sau:Tiếp nhận như Chức năng Đối số với Constrained Existentials trong Haskell

let a = A :: A -- Show A 
    b = B :: B -- Show B 
    in 
    myFunc show a b -- This should return (String, String) 

myFunc nên đầy đủ đa hình trong chữ ký của show, vì vậy có thể chấp nhận ab với các loại khác nhau thỏa mãn Show.

Đây là nỗ lực của tôi với các phần mở rộng GHC RankNTypes, ConstraintKinds, KindSignatures:

myFunc :: forall (k :: * -> Constraint) a b d. (k a, k b) 
      => (forall c. k c => c -> d) -> a -> b -> (d, d) 

Mục đích chính của tôi là để hiểu làm thế nào các phần mở rộng hoạt động; nhưng mắt của tôi, nó có vẻ như tôi đang nói GHC rằng có một hạn chế k rằng một số ab đáp ứng, và đó cũng là một chức năng (forall c. k c => c -> d) có thể mất bất kỳ loại c đáp ứng k và trả về một cụ d, bây giờ, dưới những điều kiện , tôi muốn áp dụng các chức năng để ab để có được một tuple (d,d)

Sau đây là cách GHC phàn nàn:

Could not deduce (k0 a, k0 b) 
from the context (k a, k b) 
    bound by the type signature for 
      myFunc :: (k a, k b) => 
         (forall c. k c => c -> d) -> a -> b -> (d, d) 
    at app/Main.hs:(15,11)-(16,56) 
In the ambiguity check for the type signature for ‘myFunc’: 
    myFunc :: forall (k :: * -> Constraint) a b d. 
      (k a, k b) => 
      (forall c. k c => c -> d) -> a -> b -> (d, d) 
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes 
In the type signature for ‘myFunc’: 
    myFunc :: forall (k :: * -> Constraint) a b d. (k a, k b) => 
      (forall c. k c => c -> d) -> a -> b -> (d, d) 

... 

Could not deduce (k c) 
from the context (k a, k b) 
    bound by the type signature for 
      myFunc :: (k a, k b) => 
         (forall c. k c => c -> d) -> a -> b -> (d, d) 
    at app/Main.hs:(15,11)-(16,56) 
or from (k0 c) 
    bound by the type signature for myFunc :: k0 c => c -> d 
    at app/Main.hs:(15,11)-(16,56) 
In the ambiguity check for the type signature for ‘myFunc’: 
    myFunc :: forall (k :: * -> Constraint) a b d. 
      (k a, k b) => 
      (forall c. k c => c -> d) -> a -> b -> (d, d) 
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes 
In the type signature for ‘myFunc’: 
    myFunc :: forall (k :: * -> Constraint) a b d. (k a, k b) => 
      (forall c. k c => c -> d) -> a -> b -> (d, d) 
app/Main.hs15:40 

tôi thiếu gì?

+1

tôi giả sử bạn có nghĩa là đa hình trong những hạn chế đối số chức năng có thể có, bởi vì nếu không bạn chỉ có thể viết '(Hiển thị a, Hiển thị b) => (forall x. Hiển thị x => x -> Chuỗi) -> a -> b -> (String, String)'? Điều đó chỉ yêu cầu 'RankNTypes'. – Cubic

+0

Đó là sự thật, tôi không muốn đề cập đến 'Hiển thị'. – enobayram

Trả lời

5

Vấn đề là chỉ cần chuyển hàm (forall c . k c => c -> d) làm đối số là không đủ để trình kiểm tra loại xác định rõ ràng thực tế là k là gì. Đi qua các hạn chế làm việc một cách rõ ràng và bạn thậm chí không cần bên ngoài forall hoặc loại rõ ràng:

import Data.Proxy 

myFunc :: (k a, k b) => Proxy k -> (forall c. k c => c -> d) -> a -> b -> (d, d) 
myFunc _ f a b = (f a, f b) 

và sau đó

let (c, d) = myFunc (Proxy :: Proxy Show) show a b 
+0

Tôi thấy, cảm ơn rất nhiều; điều đó cũng giải thích ý nghĩa của GHC bằng 'Để trì hoãn việc kiểm tra sự mơ hồ để sử dụng các trang web, kích hoạt AllowAmbiguousTypes', vì tôi thường mong đợi việc kiểm tra đó xảy ra trên trang gọi. Tất nhiên, suy nghĩ về nó bây giờ, hệ thống kiểu của Haskell luôn luôn cố gắng nắm bắt các vấn đề cục bộ, không giống như, nói, C + + mẫu mà trì hoãn gần như tất cả mọi thứ để instantiation. – enobayram

+2

Với GHC8, sử dụng '-XAllowAmbiguousTypes' và' -XTypeApplications' cung cấp một giải pháp khác; đối số 'Proxy' biến mất, và sau đó bạn có' myFunc f a b = (f a, f b) 'và' myFunc @Show hiển thị b' tại trang gọi. –

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