List 如何增强小Haskell代码片段

List 如何增强小Haskell代码片段,list,haskell,List,Haskell,就在最近,我开始尝试haskell。 尝试不同的练习很有趣,但有时我会觉得,我找到的解决方案远非优雅:下面的代码Snipplet将找到列表中最长的子序列,它将满足给定的条件(例如大写字母等) 你能帮一个noob把所有的东西都做得更短更优雅吗?我们非常感谢你的每一个建议 import Data.Char longer :: [a] -> [a] -> [a] longer x y = if length x > length y t

就在最近,我开始尝试haskell。 尝试不同的练习很有趣,但有时我会觉得,我找到的解决方案远非优雅:下面的代码Snipplet将找到列表中最长的子序列,它将满足给定的条件(例如大写字母等)

你能帮一个noob把所有的东西都做得更短更优雅吗?我们非常感谢你的每一个建议

import           Data.Char

longer :: [a] -> [a] -> [a]
longer x y = if length x > length y
             then x
             else y

longest :: [[a]]->[a]
longest  = foldl longer []

nextSequence :: (a->Bool) -> [a] ->([a],[a])
nextSequence f x = span f (dropWhile (not . f) x)


longestSubsequence :: (a -> Bool) -> [a] -> [a]
longestSubsequence _ x | null x = []
longestSubsequence f x =
     longest $  (\y -> [fst y , longestSubsequence f $ snd y]) (nextSequence f x)


testSequence :: String
testSequence = longestSubsequence Data.Char.isUpper
    "hkerhklehrERJKJKJERKJejkrjekERHkhkerHERKLJHERJKHKJHERdjfkj"

首先,您可以这样定义
最长的

import Data.Function
import Data.List

longest :: [[a]] -> [a]
longest = maximumBy (compare `on` length)
import Data.List

getSatisfyingSubseqs :: (a -> Bool) -> [a] -> [[a]]
getSatisfyingSubseqs f = filter (f . head) . groupBy same 
    where same x y = f x == f y
要得到满足给定条件的所有子序列,可以编写如下函数:

import Data.Function
import Data.List

longest :: [[a]] -> [a]
longest = maximumBy (compare `on` length)
import Data.List

getSatisfyingSubseqs :: (a -> Bool) -> [a] -> [[a]]
getSatisfyingSubseqs f = filter (f . head) . groupBy same 
    where same x y = f x == f y
在这里,我们将条件产生相同结果的元素分组,并只过滤满足条件的子序列

总共:

longestSubsequence :: (a -> Bool) -> [a] -> [a]
longestSubsequence f = longest . getSatisfyingSubseqs f
更新:如果你想把它缩短,你可以扔掉辅助函数,一次写出全部:

longestSubsequence :: (a -> Bool) -> [a] -> [a]
longestSubsequence f = maximumBy (compare `on` length) . filter (f . head) . groupBy same 
    where same x y = f x == f y
(别忘了进口商品)
您可以在那里运行它:

首先,您可以像下面这样定义您的
最长

import Data.Function
import Data.List

longest :: [[a]] -> [a]
longest = maximumBy (compare `on` length)
import Data.List

getSatisfyingSubseqs :: (a -> Bool) -> [a] -> [[a]]
getSatisfyingSubseqs f = filter (f . head) . groupBy same 
    where same x y = f x == f y
要得到满足给定条件的所有子序列,可以编写如下函数:

import Data.Function
import Data.List

longest :: [[a]] -> [a]
longest = maximumBy (compare `on` length)
import Data.List

getSatisfyingSubseqs :: (a -> Bool) -> [a] -> [[a]]
getSatisfyingSubseqs f = filter (f . head) . groupBy same 
    where same x y = f x == f y
在这里,我们将条件产生相同结果的元素分组,并只过滤满足条件的子序列

总共:

longestSubsequence :: (a -> Bool) -> [a] -> [a]
longestSubsequence f = longest . getSatisfyingSubseqs f
更新:如果你想把它缩短,你可以扔掉辅助函数,一次写出全部:

longestSubsequence :: (a -> Bool) -> [a] -> [a]
longestSubsequence f = maximumBy (compare `on` length) . filter (f . head) . groupBy same 
    where same x y = f x == f y
(别忘了进口商品) 您可以在那里运行它:

这个函数在这里可能非常方便。还要注意
f(a,b)=(a,fb)
。由于
长度
检查,可能效率不高,但它应该可以完成这项工作

lss :: (a -> Bool) -> [a] -> [a]
lss f []        = []
lss f ls@(x:xs) = if f x then longer (lss f <$> span f ls)
                         else lss f xs
                  where
                  longer ::([a],[a]) -> [a]
                  longer (xs,ys) = if length xs >= length ys then xs else ys
lss::(a->Bool)->[a]->[a]
lss f[]=[]
lss f ls@(x:xs)=如果f x则更长(lss f跨度f ls)
else lss f xs
哪里
更长::([a],[a])->[a]
更长(xs,ys)=如果长度xs>=长度ys,则为xs-else-ys
该功能在这里可能非常方便。还要注意
f(a,b)=(a,fb)
。由于
长度
检查,可能效率不高,但它应该可以完成这项工作

lss :: (a -> Bool) -> [a] -> [a]
lss f []        = []
lss f ls@(x:xs) = if f x then longer (lss f <$> span f ls)
                         else lss f xs
                  where
                  longer ::([a],[a]) -> [a]
                  longer (xs,ys) = if length xs >= length ys then xs else ys
lss::(a->Bool)->[a]->[a]
lss f[]=[]
lss f ls@(x:xs)=如果f x则更长(lss f跨度f ls)
else lss f xs
哪里
更长::([a],[a])->[a]
更长(xs,ys)=如果长度xs>=长度ys,则为xs-else-ys

您的
longer
函数使用
length
,这意味着如果任何一个输入都是无限的,它就不起作用。但是,如果最多有一个是无限的,则可以对其进行改进:

longer l1 l2 = go l1 l2
  where
    go [] _ = l2
    go _ [] = l1
    go (_:xs) (_:ys) = go xs ys

这也是一种性能优化。以前,如果您有一个10元素列表和一个1000万元素列表,那么在返回它之前,它将遍历1000万元素列表中的所有1000万元素。在这里,它将在到达第11个元素时立即返回它。

您的
longer
函数使用
length
,这意味着如果任何一个输入都是无限的,它将不起作用。但是,如果最多有一个是无限的,则可以对其进行改进:

longer l1 l2 = go l1 l2
  where
    go [] _ = l2
    go _ [] = l1
    go (_:xs) (_:ys) = go xs ys

这也是一种性能优化。以前,如果您有一个10元素列表和一个1000万元素列表,那么在返回它之前,它将遍历1000万元素列表中的所有1000万元素。在这里,它将在到达第11个元素时立即返回它。

不确定这是否是您要查找的100%,但标准库函数正是这样做的。(我看到您的实现使用了它的近亲
dropWhile
)注意
takeWhile
的实现是一个非常简单的递归定义,您肯定不需要所有这些辅助函数@谢谢你的回复。我很想摆脱所有这些辅助功能,但就是不知道怎么做。首先,我使用takeWhile,但随着span的出现,它看起来更简单。如果我理解正确,takeWhile-从条件适用的列表开始列出所有元素,但我搜索的是条件适用的最长子列表-因此,例如:aaaaaaaabbbbbbaaaaaaaaaabbbbbbbb ccccc dddddddddddddddddddddddddd aaa应该返回dddddddddddddddddd。有没有可能只用一个小函数就可以做到这一点?哦,我明白了,对不起。我以为你只是想写你自己版本的takeWhile(不确定你是否知道它已经存在)我在我的答案中添加了一个简短的版本,除了前面的版本,也许你会喜欢it@YuriKovalenko嘿,从所有的建议来看,你的缩短版似乎是最好的,我真的很喜欢!不确定这是否是您要查找的100%,但标准库函数正是这样做的。(我看到您的实现使用了它的近亲
dropWhile
)注意
takeWhile
的实现是一个非常简单的递归定义,您肯定不需要所有这些辅助函数@谢谢你的回复。我很想摆脱所有这些辅助功能,但就是不知道怎么做。首先,我使用takeWhile,但随着span的出现,它看起来更简单。如果我理解正确,takeWhile-从条件适用的列表开始列出所有元素,但我搜索的是条件适用的最长子列表-因此,例如:aaaaaaaabbbbbbaaaaaaaaaabbbbbbbb ccccc dddddddddddddddddddddddddd aaa应该返回dddddddddddddddddd。有没有可能只用一个小函数就可以做到这一点?哦,我明白了,对不起。我以为你只是想写你自己版本的takeWhile(不确定你是否知道它已经存在)我在我的答案中添加了一个简短的版本,除了前面的版本,也许你会喜欢it@YuriKovalenko嘿,从所有的建议来看,你的缩短版似乎是最好的,我真的很喜欢!非常感谢。哇,太短了:)谢谢你!哇,太短了:)谢谢你!这很方便