Write Yourself a Scheme in 48 Hoursを読んでいる。5章の評価2の最後あたり。
Schemeにはゆるく等価性を評価するequal?ってやつ。
(eqv? 2 "2")
#f
(equal? 2 "2")
#t
これを実装するために異る型のリストを作りmapMで順番に評価していく
data Unpacker = forall a. Eq a => AnyUnpacker (LispVal -> ThrowsError a)
unpackEquals :: LispVal -> LispVal -> Unpacker -> ThrowsError Bool
unpackEquals arg1 arg2 (AnyUnpacker unpacker) =
do unpacked1 <- unpacker arg1
unpacked2 <- unpacker arg2
return $ unpacked1 == unpacked2
`catchError` (const $ return False)
-- or :: [Bool] -> Bool
equal :: [LispVal] -> ThrowsError LispVal
equal [arg1, arg2] = do
primitiveEquals <- liftM or $ mapM (unpackEquals arg1 arg2)
[AnyUnpacker unpackNum, AnyUnpacker unpackStr, AnyUnpacker unpackBool]
eqvEquals <- eqv [arg1, arg2]
return $ Bool $ (primitiveEquals || let (Bool x) = eqvEquals in x)
equal badArgList = throwError $ NumArgs 2 badArgList
よろしくやってくれるデータ型を定義すればいいらしい。
ちょっとよくわからなかったので、適当な例をつくってみることにした。
{-# LANGUAGE ExistentialQuantification #-}
data HeteroEq = forall a. Eq a => HeteroEq (a -> Bool)
heterolist = [HeteroEq (3==), HeteroEq ("test"==), HeteroEq (True==)]
でもちょっとよくわからん。
追記 120701
これを読めばいいのかな