haskell - 在 Haskell 中使用参数作为模式

标签 haskell pattern-matching

是否可以创建一个将 Foo 或 Bar 作为参数并返回在其模式匹配中使用该参数的函数的通用函数?

例如,如果我有

isFoo :: SomeData -> Bool
isFoo (Foo _) = True
isFoo _       = False

isBar :: SomeData -> Bool
isBar (Bar _) = True
isBar _       = False

有没有办法创建一个通用函数,比如
checkType :: SomeClass -> SomeData -> Bool
checkType (SomeClass _) = True
checkType _ = False

我意识到情况看起来有点奇怪,实际用例稍微复杂一些,但问题是相同的。

我试图重构的实际代码如下
isString :: [LispVal] -> ThrowsError LispVal
isString [(String _)] = return $ Bool True
isString ((String _):xs) = isString xs >>= unpackBool >>= return . Bool
isString _ = return $ Bool False

isSymbol :: [LispVal] -> ThrowsError LispVal
isSymbol [(Atom _)] = return $ Bool True
isSymbol ((Atom _):xs) = isSymbol xs >>= unpackBool >>= return . Bool
isSymbol _ = return $ Bool False

isNumber :: [LispVal] -> ThrowsError LispVal
isNumber [(Number _)] = return $ Bool True
isNumber ((Number _):xs) = isNumber xs >>= unpackBool >>= return . Bool
isNumber _ = return $ Bool False

所以我想要一些方法让它更干燥

最佳答案

Prism s来自 lens 库可以充当“一流的模式”。要为您的数据类型定义棱镜:

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data SomeData = Foo Int 
              | Bar Char

-- Will create prisms named _Foo and _Bar
$(makePrisms ''SomeData)

由于Prism s 有效 Fold s,我们可以将它们传递给 has 函数来自 Control.Lens.Fold :
*Main> has _Foo (Foo 5)
True
*Main> has _Bar (Foo 5)
False

棱镜作为一流模式的另一个有趣应用是在参数与棱镜匹配的情况下“覆盖”函数的行为。您可以使用 outside 来自 Control.Lens.Prism 要做到这一点。 outside是一个接受 Prism 的函数并返回 Lens对于函数,它允许您“设置”特殊情况。例如:
functionToOverride :: SomeData -> Int
functionToOverride = const 5

-- If the arg is a Foo, return the contained int + 1 
newFunction :: SomeData -> Int
newFunction = functionToOverride & outside _Foo .~ succ

测试这两个功能:
*Main> functionToOverride (Foo 77)
5
*Main> newFunction (Bar 'a')
5
*Main> newFunction (Foo 77)
78

关于haskell - 在 Haskell 中使用参数作为模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20774475/

相关文章:

Haskell IO 字符串 -> 列表

haskell - 为什么要加入。 (flip fmap) 有类型 ((A -> B) -> A) -> (A -> B) -> B?

string - 在 KMP 算法中发生不匹配时转移文本的原因是什么?

makefile - 如何在目录列表中应用通配符

haskell - 任何人都可以解释这个错误吗?无法匹配类型 `Integer'

haskell - 'match' 如何在 Haskell 的 FGL 中实现为 O(1)?

macos - 如何在 OSX El Capitan 上运行 Haskell

Java 匹配器模式问题

function - Haskell 中与(高阶)函数的模式匹配

sql - PostgreSQL : Pattern matching of values starting with "IR"