我以函数的形式构建了一个数据结构,它输出某些字符串以响应某些输入字符串,如下所示:
type mydict = String -> String
emptydict :: mydict
emptydict _ = "not found"
现在我可以通过执行以下操作将条目添加到此词典中:
addentry :: String -> String -> mydict -> mydict
addentry s1 s2 d s
| s1 == s = s2
| otherwise = d s
要查找s2,我只需输入s1并查看我的字典
looky :: String -> mydict -> String
looky s1 d = d s1 --gives s2
我的目标是创建另一个函数patternmatch
,我可以在其中检查哪个s1与以特定模式开头的s2相关联。现在模式匹配本身不是问题,但我不知道如何跟踪我输入的条目,即输出的输出不是"not found"
?
我的想法是尝试跟踪我在addentry
函数中输入的所有s1,并将它们添加到单独的列表中。在patternmatch
中,我会将列表元素提供给looky
,这样我就可以找回相关的s2并检查它们是否与模式匹配。
所以我的问题:
1)此列表构建方法是否良好,或者是否有更好的方法来识别将函数定义为"not found"
以外的其他内容的输入?
2)如果这是正确的方法,我将如何跟踪s1?我想的是:
addentry s1 s2 d s
| last (save s1) == s = s2
| otherwise = d s1
然后save s1
是一个生成带有所有s1的列表的函数。然后,last (save s1)
会返回最新的s1
。非常感谢有关实施save s1
或其他指示的任何帮助。非常感谢。
答案 0 :(得分:2)
您的设计是硬编码的,因此查找密钥的唯一标准是提供相同的密钥。您需要的是一种更灵活的方法,可以让您提供平等以外的标准。我冒昧地使你的代码更通用,并使用更多的传统名称来实现这些功能:
import Prelude hiding (lookup)
-- instead of k -> Maybe v, we represent the dictionary as
-- (k -> Bool) -> Maybe v where k -> Bool is the criteria
-- on which to match the key. by using Maybe v we can signal
-- that no qualifying key was found by returning Nothing
-- instead of "not found"
newtype Dict k v = Dict ((k -> Bool) -> Maybe v)
empty :: Dict k v
empty = Dict $ const Nothing
-- insert a new key/value pair
insert :: k -> v -> Dict k v -> Dict k v
insert k v d = Dict $ \f -> if f k then Just v else lookupBy f d
-- lookup using the given criteria
lookupBy :: (k -> Bool) -> Dict k v -> Maybe v
lookupBy f (Dict d) = d f
-- lookup using the default criteria (equality with some given key)
lookup :: Eq k => k -> Dict k v -> Maybe v
lookup k = lookupBy (k==)
-- your criteria
startsWith :: String -> String -> Bool
startsWith s = undefined -- TODO
lookupByPrefix :: String -> Dict String v -> Maybe v
lookupByPrefix = lookupBy . startsWith
我应该提一下,虽然这是功能性编程实践和一般大脑扩展的一个很好的练习,但它是实现地图的一种可怕方式。对列表是等价的,更容易理解。
作为旁注,我们可以轻松地为此类型定义Functor
的实例:
instance Functor (Dict k) where
fmap f d = Dict $ \g -> fmap f (lookupBy g d)