Haskell 如何将值列表转换为数据构造函数';s参数?
我正在处理一个web请求,并试图保存一个潜在的实体(用户/地址1)。主要的问题是,如何将字符串列表转换为参数,并将其转换为函数,其中列表可以是任意长度的 我已经看过了,但这似乎是一个解决方案,只有在事先知道参数的数量Haskell 如何将值列表转换为数据构造函数';s参数?,haskell,Haskell,我正在处理一个web请求,并试图保存一个潜在的实体(用户/地址1)。主要的问题是,如何将字符串列表转换为参数,并将其转换为函数,其中列表可以是任意长度的 我已经看过了,但这似乎是一个解决方案,只有在事先知道参数的数量 我正在寻找一个大致如下的函数: f :: [String] -> (? -> c) -> Maybe c f fields c = undefined 所以我只需要传递数据构造函数(User/Address1)和字符串列表 示例: f ufields用户将返回
我正在寻找一个大致如下的函数:
f :: [String] -> (? -> c) -> Maybe c
f fields c = undefined
所以我只需要传递数据构造函数(User/Address1)和字符串列表
示例:
f ufields用户
将返回Just(用户“chris”“str”)
f[“chris”]用户
将返回Nothing
f[]用户
将返回Nothing
f afields Address1
将返回Just(Address1“earth”)
不使用TemplateHaskell是否可以实现这一点?我可以手动实现上述功能,但需要额外键入大量内容:
data User = User String String deriving (Show)
data Address1 = Address1 String deriving (Show)
data EntityType = UserEntity | AddressEntity
data EntityContainer = UserContainer User | AddressContainer Address1
f :: EntityType -> [String] -> Maybe EntityContainer
f UserEntity (p:p':[]) = Just $ UserContainer $ User p p'
f AddressEntity (p:[]) = Just $ AddressContainer $ Address1 p
f _ _ = Nothing
printPossibleEntity :: [String] -> EntityType -> IO ()
printPossibleEntity fields entityType =
case (f entityType fields) of
Just (UserContainer u) -> print u
Just (AddressContainer a) -> print a
Nothing -> print "No entity matched"
main :: IO ()
main = do
let ufields = ["chris", "str"]
let afields = ["earth"]
printPossibleEntity ufields UserEntity
printPossibleEntity afields AddressEntity
printPossibleEntity [] AddressEntity
哪些产出:
User "chris" "str"
Address1 "earth"
"No entity matched"
让我先说一句,你几乎肯定不应该使用这个 做这类事情的通常方法是使用重叠的多参数类型类 第一次尝试 在这里,它正在发挥作用:
ghci> data User = User String String deriving Show
ghci> data Address1 = Address1 String deriving Show
ghci> packArgs ["chris","str"] User :: Maybe User
Just (User "chris" "str")
ghci> packArgs ["chris"] User :: Maybe User
Nothing
ghci> packArgs [] User :: Maybe User
Nothing
ghci> packArgs ["earth"] Address1 :: Maybe Address1
Just (Address1 "earth")
ghci> data User = User String String deriving Show
ghci> data Address1 = Address1 String deriving Show
ghci> packArgs ["chris","str"] User
Just (User "chris" "str")
ghci> packArgs ["chris"] User
Nothing
ghci> packArgs [] User
Nothing
ghci> packArgs ["earth"] Address1
Just (Address1 "earth")
问题是,我们需要类型注释才能工作。简而言之,Haskell需要知道您的预期回报类型是什么。我们可以用一些类型族来解决这个问题
第二次尝试
在这里,它正在发挥作用:
ghci> data User = User String String deriving Show
ghci> data Address1 = Address1 String deriving Show
ghci> packArgs ["chris","str"] User :: Maybe User
Just (User "chris" "str")
ghci> packArgs ["chris"] User :: Maybe User
Nothing
ghci> packArgs [] User :: Maybe User
Nothing
ghci> packArgs ["earth"] Address1 :: Maybe Address1
Just (Address1 "earth")
ghci> data User = User String String deriving Show
ghci> data Address1 = Address1 String deriving Show
ghci> packArgs ["chris","str"] User
Just (User "chris" "str")
ghci> packArgs ["chris"] User
Nothing
ghci> packArgs [] User
Nothing
ghci> packArgs ["earth"] Address1
Just (Address1 "earth")
为什么需要对构造函数进行抽象?如果您事先不知道其类型,您将如何使用
f
的返回值?我将创建一个typeclass,其中User
将有一个与此相关的实例。因此,save(用户“chris”“str”)
可以作为一个例子。这似乎是一个糟糕的设计。与其尝试创建一个完成所有工作的函数,还不如创建几个更小、更简单的函数,每个函数处理不同的实体类型。
ghci> data User = User String String deriving Show
ghci> data Address1 = Address1 String deriving Show
ghci> packArgs ["chris","str"] User
Just (User "chris" "str")
ghci> packArgs ["chris"] User
Nothing
ghci> packArgs [] User
Nothing
ghci> packArgs ["earth"] Address1
Just (Address1 "earth")