在列表上折叠部分应用的值构造函数?
Fold a partially applied value constructor over a list?
我有这样的类型:
data MessageType = Debug | Error deriving (Show, Eq)
type Code = Int
type Info = String
data Message = Message MessageType Code Info
和一个接受字符串和 returns 一个 Message
:
的函数
parseMsg :: String -> Message
到目前为止我已经写了一个粗略的状态机:
parseMsg line = fold (words line) Message
where fold ("D":xs) msgCtr = fold' xs (msgCtr Debug)
fold ("E":xs) msgCtr = fold' xs (msgCtr Error)
fold' (code:xs) msgCtr = fold'' xs (msgCtr (readCode code))
fold'' rest msgCtr = msgCtr (unwords rest)
readCode code = read code::Int
但我更愿意在实际的 foldl
或 foldr
中执行此操作。
foldl (\msgVConstructor el -> msgVConstructor el) LogMessage (words line)
这个想法是折叠函数 (Message -> String -> Message)
以便累加器 Message
部分应用于字符串中的单词。但是,我得到这个错误
Constructor ‘Message’ should have 3 arguments, but has been given none**strong text**
我的意思是值构造函数不能在折叠中部分应用。有没有办法做到这一点?
嗯,如果我没理解错的话,你基本上想在构造函数中解析三个参数。这实际上不是 foldr
或 foldl
应该做的。 foldr
基本上是对列表的 变形 。您将 (:)
替换为 f
,并将 []
替换为初始累加器 x0
。但是由于在编译时不知道列表中的元素数量,因此 f
的类型总是需要具有 相同的 类型: a -> b -> b
和 a
列表中元素的类型,b
折叠输出的类型。
但是,如果我们仔细查看您提供的代码,就会发现这 根本不像 fold
。您基本上有一个包含三个元素的构造函数,目标是将它们转换为 Message
。您可以通过分别解释参数来做到这一点:
parseMsg line = Message (<b>mtype</b> st) <b>code</b> <b>rest</b>
where (st : sc : sr) = words line
<b>mtype</b> "D" = Debug
<b>mtype</b> "E" = Error
<b>code</b> = read sc :: Int
<b>rest</b> = unwords sr
我们因此将line
的words
解包为st
、sc
和sr
,然后将第一个,第二个和剩余的元素处理成Message
的参数(用mtype
一个函数将字符串翻译成对应的MessageType
),它读取第二个参数作为一个Int
,最后将rest
生成为unwords sr
。然后使用这些参数来构建消息。
我有这样的类型:
data MessageType = Debug | Error deriving (Show, Eq)
type Code = Int
type Info = String
data Message = Message MessageType Code Info
和一个接受字符串和 returns 一个 Message
:
parseMsg :: String -> Message
到目前为止我已经写了一个粗略的状态机:
parseMsg line = fold (words line) Message
where fold ("D":xs) msgCtr = fold' xs (msgCtr Debug)
fold ("E":xs) msgCtr = fold' xs (msgCtr Error)
fold' (code:xs) msgCtr = fold'' xs (msgCtr (readCode code))
fold'' rest msgCtr = msgCtr (unwords rest)
readCode code = read code::Int
但我更愿意在实际的 foldl
或 foldr
中执行此操作。
foldl (\msgVConstructor el -> msgVConstructor el) LogMessage (words line)
这个想法是折叠函数 (Message -> String -> Message)
以便累加器 Message
部分应用于字符串中的单词。但是,我得到这个错误
Constructor ‘Message’ should have 3 arguments, but has been given none**strong text**
我的意思是值构造函数不能在折叠中部分应用。有没有办法做到这一点?
嗯,如果我没理解错的话,你基本上想在构造函数中解析三个参数。这实际上不是 foldr
或 foldl
应该做的。 foldr
基本上是对列表的 变形 。您将 (:)
替换为 f
,并将 []
替换为初始累加器 x0
。但是由于在编译时不知道列表中的元素数量,因此 f
的类型总是需要具有 相同的 类型: a -> b -> b
和 a
列表中元素的类型,b
折叠输出的类型。
但是,如果我们仔细查看您提供的代码,就会发现这 根本不像 fold
。您基本上有一个包含三个元素的构造函数,目标是将它们转换为 Message
。您可以通过分别解释参数来做到这一点:
parseMsg line = Message (<b>mtype</b> st) <b>code</b> <b>rest</b>
where (st : sc : sr) = words line
<b>mtype</b> "D" = Debug
<b>mtype</b> "E" = Error
<b>code</b> = read sc :: Int
<b>rest</b> = unwords sr
我们因此将line
的words
解包为st
、sc
和sr
,然后将第一个,第二个和剩余的元素处理成Message
的参数(用mtype
一个函数将字符串翻译成对应的MessageType
),它读取第二个参数作为一个Int
,最后将rest
生成为unwords sr
。然后使用这些参数来构建消息。