我有以下代码:
-- A CharBox is a rectangular matrix of characters
data CharBox = CharBox [String]
deriving Show
-- Build a CharBox, ensuring the contents are rectangular
mkCharBox :: [String] -> CharBox
mkCharBox [] = CharBox []
mkCharBox xxs@(x:xs) = if (all (\s -> (length s) == length x) xs)
then CharBox xxs
else error "CharBox must be a rectangle."
[[Char]]
必须是矩形的(即所有子列表必须具有相同的长度)才能使模块中的许多功能正常工作。在模块内部,我总是使用mkCharBox
“构造函数”,所以我不必一直强制执行此约束。
最初我希望我的模块声明看起来像这样:
module CharBox (
CharBox, -- No (CharBox) because it doesn't enforce rectangularity
mkCharBox
) where
但是这样,我模块的用户无法在CharBox
上进行模式匹配。在另一个模块中我做了
findWiresRight :: CharBox -> [Int]
findWiresRight (CharBox xs) = elemIndices '-' (map last xs)
并且ghci抱怨:Not in scope: data constructor 'CharBox'
是否可以强制执行CharBox
仅包含矩形数组的约束,同时仍然允许模式匹配?(如果不可能,我也有兴趣知道技术原因。我发现在探索这样的限制时,Haskell通常需要学习很多东西)
答案 0 :(得分:7)
在vanilla Haskell中,隐藏构造函数并支持模式匹配是不可能的。
解决这个问题的常用方法是:
或:
答案 1 :(得分:2)
最简单的解决方案是向模块添加提取功能:
extract :: CharBox -> [String]
extract (CharBox xs) = xs
然后使用它而不是模式匹配:
findWiresRight :: CharBox -> [Int]
findWiresRight c = elemIndices '-' $ map last $ extract c