我的代码中有一堆复杂的数据构造函数,我希望借助新的Pattern Synonyms
语言扩展稍微理顺一下。但是,在我看来,如果没有专门的视图函数来删除手头的特定数据构造函数,我就无法实现它,只是将一些常用的库函数应用于内部数据。我希望我可以对构造函数进行模式匹配,然后将通常的库函数作为视图应用,从而摆脱了显式定义专用视图函数的需要。唉,我无法弄清楚如何做到这一点。
编写专用视图函数的不太明显的缺点是,如果模式匹配失败,则会出现提及视图函数名称的错误,从而挫败了模式同义词的抽象。所以我不能在我的视图函数中只有一个模式匹配失败,但我宁愿显式返回一个Maybe值,这样我就无法匹配模式本身的Just。这正是样板。
对于在这种情况下如何最好地安排代码,我将不胜感激,包括将模式同义词用于这种方式是否真的是一种好的做法。
这是我专门针对这个问题编写的示例代码,与我实际编写的代码非常相似。我尽力简明扼要。我还到处都提出了评论和例子 - 我希望它能让读者感到更加恼火。您也可以立即在ghci
中运行代码。
{-# LANGUAGE
PatternSynonyms
, ViewPatterns
#-}
module PatternSynonym where
-- ### Type definitions.
-- | This wrapper may have been introduced to harden type safety, or define a
-- typeclass instance. Its actual purpose does not matter for us here.
newtype Wrapped a = Wrap { unWrap :: a } deriving (Eq, Show)
-- | This data type exemplifies a non-trivial collection of things.
data MaybeThings a = Some [a] | None deriving (Eq, Show)
-- | This type synonym exemplifies a non-trivial collection of things that are
-- additionally wrapped.
type MaybeWrappedThings a = MaybeThings (Wrapped a)
-- ### An example of what we may want to do with our types:
-- | This is a function that does useful work on plain (not Wrapped!) Ints.
doSomething :: [Int] -> [Int]
doSomething = filter even
-- ^
-- λ doSomething [2, 3, 5]
-- [2]
-- | This is the example data we may have.
example :: MaybeWrappedThings Int
example = Some [Wrap 2, Wrap 3, Wrap 5]
-- | This is a function that must only accept a collection of wrapped things,
-- but it has to unwrap them in order to do something useful.
getThings :: MaybeWrappedThings Int -> [Int]
getThings (Some wxs) = doSomething xs
where xs = unWrap <$> wxs
getThings None = [ ]
-- ^
-- λ getThings example
-- [2]
-- ### An example of how we may simplify the same logic with the help of
-- pattern synonyms.
-- | This helper function is necessary (?) in order for it to be possible to
-- define the pattern synonym.
unWrapAll :: MaybeWrappedThings a -> Maybe [a]
unWrapAll (Some wxs) = Just (unWrap <$> wxs)
unWrapAll None = Nothing
-- | This is the pattern synonym that allows us to somewhat simplify getThings.
pattern Some' :: [a] -> MaybeWrappedThings a
pattern Some' xs <- (unWrapAll -> Just xs)
where Some' = Some . fmap Wrap
-- | This is how we may define our data with the pattern synonym.
-- It's got linearly less lexemes!
example' :: MaybeWrappedThings Int
example' = Some' [2, 3, 5]
-- ^
-- λ example == example'
-- True
-- | This is how our function may look with the pattern synonym.
getThings' :: MaybeWrappedThings Int -> [Int]
getThings' (Some' xs) = doSomething xs
getThings' None = [ ]
-- ^
-- λ getThings' example'
-- [2]
--
-- λ getThings' example' == getThings example
-- True
答案 0 :(得分:2)
Haskell 有什么不能吗?
我想这个:
pattern Some' xs <- Some (coerce -> xs)
- 完美。
感谢@chi代表coerce
和@ li-yao-xia,感谢代码在与Some
数据构造函数匹配后查看变量。
这非常直观,我甚至不怀疑Haskell可以做这么多。