Giả sử tôi có các chức năng ghi nhớ sau đây. (Bỏ qua sự thật là họ trong sạch.)Xác định việc thực hiện phương pháp dựa trên các ràng buộc có sẵn
memoEq :: Eq a => (a -> b) -> a -> b
memoOrd :: Ord a => (a -> b) -> a -> b
memoHash :: Hashable a => (a -> b) -> a -> b
Bây giờ tôi muốn có một cấu trúc cho phép tôi chọn 'tốt nhất' của ba chức năng ghi nhớ ở trên. Cái gì mà về cơ bản nào sau đây:
memo f = case constraint_of_typevar_a_in f of
Eq a -> memoEq
Ord a -> memoOrd
Hashable a -> memoHash
Bạn có thể thử điều này với các lớp học kiểu nhưng bạn sẽ nhận được trường hợp chồng chéo:
class Memo a where
memo :: (a -> b) -> a -> b
instance Eq a => Memo a where
memo = memoEq
instance Ord a => Memo a where
memo = memoOrd
Tôi cũng đã cố gắng sử dụng cast
để lấy những hạn chế. Tôi nhận ra rằng điều này sẽ xảy ra vào thời gian chạy và như tôi đã nói trong #haskell đây có lẽ là một ý tưởng tồi. (Tôi đã bỏ qua các trường hợp cho memoOrd
và memoHash
vì lợi ích ngắn gọn.)
{-# LANGUAGE ImpredicativeTypes, ScopedTypeVariables #-}
module Main where
import Data.Typeable
memo :: forall a b. (Typeable a, Typeable b) => (a -> b) -> Maybe (a -> b)
memo f =
let eqf = cast f :: Eq a => Maybe (a -> b)
in case eqf of
Just eqf' -> Just $ memoEq eqf'
Nothing -> Nothing
memoEq :: Eq a => (a -> b) -> a -> b
memoEq = undefined
memoOrd :: Ord a => (a -> b) -> a -> b
memoOrd = undefined
Mã này tạo ra các thông báo lỗi sau:
cast.hs:8:19:
Could not deduce (Eq a) arising from an expression type signature
from the context (Typeable a, Typeable b)
bound by the type signature for
memo :: (Typeable a, Typeable b) => (a -> b) -> Maybe (a -> b)
at cast.hs:6:9-74
Possible fix:
add (Eq a) to the context of
the type signature for
memo :: (Typeable a, Typeable b) => (a -> b) -> Maybe (a -> b)
In the expression: cast f :: Eq a => Maybe (a -> b)
In an equation for `eqf': eqf = cast f :: Eq a => Maybe (a -> b)
In the expression:
let eqf = cast f :: Eq a => Maybe (a -> b)
in
case eqf of {
Just eqf' -> Just $ memoEq eqf'
Nothing -> Nothing }
Di chuyển Eq a
hạn chế bên trong Maybe
đưa ra một lỗi thêm không có ràng buộc Typeable1
trên phương trình.
Không thể suy ra (Typeable1 Eq) phát sinh từ việc sử dụng của `đúc' từ bối cảnh (Typeable một, Typeable b)
Là những gì tôi muốn đạt được có thể, có lẽ sử dụng Template Haskell ? Hoặc là nó hoàn toàn không thể và không mong muốn để có thể làm điều này?
Điều gì sẽ xảy ra nếu 'memoEqOrd'? bạn không cho phép nó? – josejuan
@josejuan: Đó không phải là vấn đề, tôi sẽ chọn memoOrd hoặc memoEq. Giả sử rằng có một thứ tự trên các chức năng ghi nhớ, nhưng chính xác thì điều đó không quan trọng ngay bây giờ tôi cảm thấy. –