2017-04-25 15 views
7

Tôi đã có một mô-đun nội tôi muốn cung cấp một API bên ngoài choẨn một constructor nhưng không phải là loại nhập khẩu

module Positive.Internal where 

newtype Positive a = Positive { getPositive :: a } 
    deriving (Eq, Ord) 

-- smart constructor 
toPositive :: (Num a, Ord a) => a -> Maybe (Positive a) 
toPositive a | a <= 0 = Nothing 
      | otherwise = Just $ Positive a 
-- ... 

Tôi muốn ẩn các nhà xây dựng câm, và thay thế bằng một một chiều Mẫu để người dùng vẫn có thể so khớp các giá trị mẫu, họ chỉ phải sử dụng hàm tạo thông minh để sử dụng các giá trị mới.

Vì tôi muốn mẫu và công cụ tạo hình câm sử dụng cùng tên, tôi cần phải ẩn trình tạo dựng câm để ngăn chặn các xung đột không gian tên.

Tuy nhiên, kể từ khi hàm tạo câm và tên chia sẻ loại, có một chút khó khăn khi nhập tất cả mọi thứ NHƯNG hàm tạo câm.

Hiện nay tôi đang làm điều này, mà làm việc ok:

{-# LANGUAGE PatternSynonyms #-} 
module Positive 
    (module Positive.Internal, pattern Positive 
) where 

import Positive.Internal (Positive()) 
import Positive.Internal hiding (Positive) 
import qualified Positive.Internal as Internal 

pattern Positive :: a -> Positive a 
pattern Positive a <- Internal.Positive a 

tôi có thể đơn giản hóa nhập khẩu của mình bằng cách chỉ sử dụng nhập khẩu đủ điều kiện, nhưng tôi tò mò.

Có cách nào để, trong một câu lệnh nhập, nhập tất cả Positive.Internal ngoại trừ hàm tạo câm không?

Tôi đã thử hiding (Positive(Positive)), nhưng điều đó ẩn cả loại và hàm tạo câm. Tôi đã poked về the wiki, nhưng tôi đã không nhận thấy bất kỳ cách nào để phân biệt giữa các nhà xây dựng và các loại trong danh sách hiding.

+0

Tôi mang nó ẩn constructor 'newtype' của bên trong mô-đun nội bộ không phải là một lựa chọn? Nếu có, bạn có thể đổi tên hàm tạo 'newtype' thành (nói)' Positive_', di chuyển từ đồng nghĩa 'Positive' sang mô-đun bên trong và xuất thay thế. –

+0

Tôi nghĩ câu hỏi đã được trả lời ở đây: http://stackoverflow.com/questions/8172548/is-it-possible-to-export-constructors-for-pattern-matching-but-not-for-construc Không có gì thay đổi kể từ sau đó. Điều này cho thấy GHC trac ticket không tạo ra mẫu đồng nghĩa mới nhưng chỉ sử dụng 'pattern' trên constructor hiện tại: https://ghc.haskell.org/trac/ghc/ticket/8753 Nhưng tiếc là điều này cũng sẽ export constructor, không chỉ pattern: (Bởi vì mô hình constructor theo mặc định là hai chiều – Shersh

+5

Tại sao bạn muốn pattern và ctor constructor có cùng tên? Tại sao không chỉ đặt tên cho constructor câm cái gì khác? ... – luqui

Trả lời

3

Đúng tôi nếu tôi sai, nhưng tôi gần như chắc chắn đây là những gì bạn đang tìm kiếm:

{-# LANGUAGE PatternSynonyms #-} 
module Positive 
    (module Positive.Internal, pattern Positive, foo 
) where 

import Positive.Internal hiding (pattern Positive) 
import qualified Positive.Internal as Internal (pattern Positive) 

pattern Positive :: a -> Positive a 
pattern Positive a <- Internal.Positive a 

foo :: Positive Int 
foo = Internal.Positive 5 

Internal mô-đun vẫn theo cùng một cách như nó được xác định cho đến nay. Và vì lợi ích của ví dụ:

module Negative where 

import Positive 

bar :: Maybe Int 
bar = getPositive <$> toPositive 6 

Hãy kiểm tra lại trong GHCi:

Prelude> :load Negative 
[1 of 3] Compiling Positive.Internal (Positive/Internal.hs, interpreted) 
[2 of 3] Compiling Positive   (Positive.hs, interpreted) 
[3 of 3] Compiling Negative   (Negative.hs, interpreted) 
Ok, modules loaded: Negative, Positive, Positive.Internal. 
*Negative> bar 
Just 6 
*Negative> getPositive foo 
5 
*Negative> :i Positive 
newtype Positive a = Positive.Internal.Positive {getPositive :: a} 
    -- Defined at Positive/Internal.hs:3:1 
instance [safe] Ord a => Ord (Positive a) 
    -- Defined at Positive/Internal.hs:4:17 
instance [safe] Eq a => Eq (Positive a) 
    -- Defined at Positive/Internal.hs:4:13 
*Negative> :t Positive 

<interactive>:1:1: error: 
    • non-bidirectional pattern synonym ‘Positive’ used in an expression 
    • In the expression: Positive 
+1

Hoàn hảo! Tôi không biết rằng bạn có thể chỉ định các nhà xây dựng bằng cách sử dụng từ khóa 'pattern'. Cám ơn rất nhiều. – rampion

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