识别函数不生成特定输出的输入值

时间:2017-01-19 23:07:30

标签: haskell functional-programming

我以函数的形式构建了一个数据结构,它输出某些字符串以响应某些输入字符串,如下所示:

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或其他指示的任何帮助。非常感谢。

1 个答案:

答案 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)