Có cách nào thuận tiện để sử dụng mẫu làm hàm vị ngữ không?


10

Gần đây tôi đã gặp phải tình huống cần chuyển một hàm vị ngữ sang một hàm khác và thông thường logic tôi đang tìm kiếm về cơ bản là "giá trị này có khớp với mẫu này không?"

Kết hợp mẫu dường như được ưa thích trong khai báo, dokhối và hiểu danh sách, nhưng có một số hàm lấy một vị ngữ a -> Bool, trong đó sẽ rất thuận tiện để bằng cách nào đó chuyển qua một mẫu. Ví dụ, takeWhile, until, find, span,, vv

Cho đến nay tôi đã làm \a -> case a of MyCons _ -> True; otherwise -> False, hoặc viết một chức năng được đặt tên là la let myPred (MyCons _) = True; myPred _ = False innhưng cả hai đều có vẻ xấu xí và không thành ngữ lắm. Cách "rõ ràng" (và sai) sẽ giống như thế \(MyCons _) -> Truenhưng điều đó gây ra lỗi vì là một phần, một cách tự nhiên, và thậm chí sau đó cảm giác như phải có một cách sạch hơn.

Có cách nào gọn gàng / sạch sẽ hơn để làm điều này không? Hay tôi đang đi về những thứ hoàn toàn sai lầm?


1
Có thể đây là một điều "sở thích cá nhân", nhưng, nếu bạn chỉ cần vị ngữ này ở một nơi, tôi sẽ khá hài lòng với letmệnh đề mà bạn không thích - mặc dù tôi thích wheremệnh đề tương đương nên điều này không làm lộn xộn định nghĩa chính. Tất nhiên nếu cuối cùng bạn cần tiện ích này nhiều lần thì bạn sẽ xác định nó là một chức năng cấp cao nhất.
Robin Zigmond

Nó chắc chắn hoạt động tốt. Câu hỏi của tôi phần nào được thúc đẩy bởi cách Haskell cô đọng ấn tượng thường thấy. Nó thường có cảm giác như Haskell thành ngữ có rất ít ý tưởng trùng lặp và giữ cho lông tơ ở mức tối thiểu. Vì vậy, nó thậm chí không nhất thiết là tôi nghĩ rằng let myPred...phong cách đó là xấu , nhưng nó cảm thấy dài dòng hơn tôi mong đợi cho một ý tưởng rất đơn giản, khiến tôi tự hỏi nếu tôi đang sủa sai cây.
David Sampson

2
Bạn có thể có một cái nhìn vào lăng kính (từ ống kính). Chúng giống như các mẫu có thể kết hợp hạng nhất
luqui

1
Tôi nghĩ rằng chúng ta cần xem một ví dụ về nơi bạn đang sử dụng loại hàm bậc cao hơn này. Một phần trong tôi muốn nói vấn đề là với thiết kế đòi hỏi một vị ngữ như vậy ngay từ đầu.
chepner

Cách Haskell98, đối với điều này, là xác định hàm khớp trường hợp (giải cấu trúc) cho kiểu dữ liệu của bạn, như maybe :: b -> (a -> b) -> Maybe a -> bbool :: a -> a -> Bool -> asau đó sử dụng nó với (các) hàm tạo Boolean làm đối số. ví dụ myCons z f (MyCons x) = f x ; myCons z f _ = z, sau đó gọi myCons False (const True) aMyConsValue. đây gần như là những gì bạn đã viết, chỉ cần có thêm một mức độ "gián tiếp" / "trừu tượng" thông qua (các) đối số chức năng, được đưa vào trong đó.
Will Ness

Câu trả lời:


7

Bạn có thể sử dụng tiện ích mở rộng ngôn ngữ LambdaCase để sử dụng \case MyCons _ -> True; _ -> False, mặc dù điều này không lưu được nhiều ký tự.

Tôi tin rằng bạn có thể viết một loạt các chức năng constructedWith :: (Generic a) => (b -> a) -> a -> Bool, constructedWith2 :: (Generic a) => (b -> c -> a) -> a -> Boolnhưng tôi không đủ năng lực với Generics để thực hiện nó mà không cần vài giờ thử nghiệm mọi thứ. Tôi sẽ thử điều này, và chỉnh sửa câu trả lời của tôi nếu tôi có thể tìm ra nó, hoặc nếu nó là một ngõ cụt.

EDIT: Vâng, bạn có thể làm điều đó! Đây là một liên kết đến mã của tôi, thực hiện tất cả từ đầu:

https://repl.it/@lalaithion/ConstructedWith

Tuy nhiên, sử dụng một cái gì đó như http://hackage.haskell.org/package/generic-deriving-1.13.1/docs/Generics-Deriving-ConNames.html cho tất cả các hệ thống ống nước mã chung có thể tốt hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.