2011-05-18 27 views
5

Tôi muốn viết một hàm mang theo cảPattern khớp nơi mô hình dựa trên một (chức năng) tham số

  • một constructor giá trị cho một kiểu dữ liệu đại số nhất định, và
  • một giá trị thực tế cùng loại đó,

và xác định liệu giá trị đã cho có được tạo từ "hàm tạo đã cho hay không. Khớp mẫu có vẻ giống như sự phù hợp tự nhiên cho điều này, nhưng mẫu phù hợp với sẽ phải là tham số hàm thay vì tên hàm dựng mã cứng.

Mã bên dưới là những gì tôi đã thử, nhưng GHC báo cáo lỗi phân tích cú pháp trên dòng được chỉ định.

Có cách nào để thực hiện việc này không?

data FooBar = Foo Int | Bar String 

-- Imagine that these are useful functions. 
processInt :: Int -> String 
processInt = show 
processString :: String -> String 
processString = id 

-- This should take one of the above functions and adapt it to operate on 
-- FooBar values of compatible "type". Values that match the given FooBar 
-- constructor should be "unwrapped" and passed to the given function. 
typeCheck :: (a -> FooBar) -> (a -> String) -> (FooBar -> Maybe String) 
typeCheck constructor func fooBar = case fooBar of 
    (constructor x) -> Just (func x) -- GHC says "Parse error in pattern: constructor" 
    _ -> Nothing 

-- Define processing functions that operate on FooBars. 
processFoo :: FooBar -> Maybe String 
processFoo = typeCheck Foo processInt 
processBar :: FooBar -> Maybe String 
processBar = typeCheck Bar processString 

Trả lời

3

Ý tưởng thú vị. Tôi tự hỏi những gì bạn đang cố gắng làm, vì đây là một mô hình khá bất thường phù hợp với vấn đề.

Bạn chắc chắn có thể làm điều đó nếu bạn có thể:

  • liệt kê các nhà thầu của các loại
  • có sự bình đẳng trên các yếu tố của loại

Giống như vậy (tôi thoát ra khỏi việc áp dụng f một phần, vì đó là trực giao):

wasBuilt :: Eq t => (t -> Either t t) --^the constructor 
       -> Either t t   --^a value 
       -> Maybe t    --^the transformed result 

wasBuilt k v = case v of 
    Left x | v == k x -> Just x 
    Right x | v == k x -> Just x 
    _      -> Nothing 

Nhưng re's rất nhiều boilerplate. Vấn đề này hét lên "generics" với tôi. Hãy thử một cách tiếp cận khác và phản ánh hàm tạo cho dữ liệu, sau đó kết hợp chung về dữ liệu đó, có lẽ. Điều này sẽ cho phép bạn coi các hàm tạo là các giá trị, thay vì các hàm.


Đây là những gì tôi nghĩ, nhưng lưu ý, đây là một kỹ thuật nâng cao. Kết hợp mẫu rõ ràng trên một AST thông thường là nhiều, nhiều thành ngữ hơn:

import Generics.SYB 

-- only works for unary constructors 
sameConstructor :: (Data a, Data b) => (a -> b) -> b -> Bool 
sameConstructor k v = toConstr v == toConstr (k undefined) 

> sameConstructor (Left :: Char -> Either Char Char) (Right 'x') 
False 

> sameConstructor (Left :: Char -> Either Char Char) (Left 'x') 
True 

> sameConstructor (:[]) "haskell" 
True 
+0

Đây là máy tính RPN (chương trình thực hành) có thể có hỗn hợp các loại khác nhau (ví dụ: số và chuỗi) trên ngăn xếp. Hầu hết các chức năng hoạt động trên ngăn xếp sẽ bắt đầu bằng cách popping một số giá trị, kiểm tra xem chúng có đúng loại cho hoạt động hay không và báo cáo lỗi nếu không. Tôi đang cố gắng để loại trừ việc kiểm tra loại để tránh trùng lặp mã. – Wyzard

+0

Ah! Sẽ dễ dàng hơn nhiều nếu bạn mã hóa các thẻ loại dưới dạng giá trị đơn giản (ví dụ: 'Giá trị' Int'), thay vì hàm khởi tạo. Đó là điều làm cho ví dụ của bạn trở nên phức tạp: việc khớp mẫu trên các hàm chỉ là khó khăn. –

+0

Cảm ơn, tôi sẽ xem xét sử dụng thẻ loại số thay thế. Vì tập hợp các kiểu của tôi tương đối hạn chế, tôi cũng có thể tạo ra một họ các hàm như 'typeCheckInt',' typeCheckString', vv với hàm tạo thích hợp được mã hóa cứng trong mỗi loại.Vì đây là một chương trình thực hành, tôi nghĩ tôi sẽ thử một chút khó khăn hơn, nhưng có vẻ như tôi đã bị cắn nhiều hơn tôi có thể nhai. Tôi đã quen thuộc với generics trong ngữ cảnh của C++ và Java, nhưng không phải trong ngữ cảnh của Haskell. – Wyzard

2

Bạn có thể muốn xem Type-safe pattern combinators ngọc trai chức năng. Mặc dù nó không kết hợp độc đáo với cú pháp khớp mẫu của Haskell, nó cho phép bạn có mô đun của các mẫu lớp đầu tiên có thể tổng hợp, nếu đó là những gì bạn cần (tức là nếu tính tương thích được thêm lớn hơn sự bất tiện cú pháp).

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