Sku*_*uge 3 constructor haskell
我有这个代码
data Container = Box Int | Bag Int
inBox :: [Container] -> Int
inBox [] = 0
inBox (x:ls) | (Box i) <- x = i + inBox ls
| otherwise = inBox ls
inBag :: [Container] -> Int
inBag [] = 0
inBag (x:ls) | (Bag i) <- x = i + inBag ls
| otherwise = inBag ls
Run Code Online (Sandbox Code Playgroud)
显然InBox,InBag具有相同的结构.我想创建一个包含它们的功能.我不知道如何获取是将构造函数(Box或者Bag)作为参数传递.
理想情况下,一般功能看起来像这样:
inSome :: Constructor -> [Container] -> Int
inSome con [] = 0
inSome con (x:ls) | (con i) <- x = i + inSome con ls
| otherwise = inSome con ls
Run Code Online (Sandbox Code Playgroud)
显然这不起作用,因为构造函数不是这里定义的类型.我该怎么做?
一个想法是将它作为一个函数传递:
inSome :: (Int -> Container) -> [Container] -> Int
inSome _ [] = 0
inSome con (x:ls) | (con i) <- x = i + inSome ls
| otherwise = inSome ls
Run Code Online (Sandbox Code Playgroud)
但后来我得到了错误:
模式中的解析错误:con
因为它无法匹配这样的功能.
我想这样做的原因是因为我有一个包含二进制操作的复杂数据类型(例如+,#,::等等).我有几个函数对于这些构造函数几乎相同.我不想写所有这些并一起修改它们.我必须有办法在函数中完成它.也许有人可以在评论中提出另一种方法?
您可以完全避免使用模式匹配.
data Container = Box Int | Bag Int
unBox, unBag :: Container -> Maybe Int
unBox (Box i) = Just i
unBox _ = Nothing
unBag (Bag i) = Just i
unBag _ = Nothing
Run Code Online (Sandbox Code Playgroud)
这些函数的类型捕获了Int在打开结构时获取包含的需要Container.然后可以使用它来构建您想要的功能.
inSome :: (Container -> Maybe Int) -> [Container] -> Int
inSome get [] = 0
inSome get (x:ls) = fromMaybe 0 (get x) + inSome ls
inBag = inSome unBag
inBox = inSome unBox
Run Code Online (Sandbox Code Playgroud)
正如leftroundabout所指出的那样,"获得或失败"的模式是(大规模地)在概念中概括Lens,或者在这种情况下,概括Prism.一般来说,Prisms可以形成一种弱的一流模式,但它们在这里的使用肯定会有点过分.