Haskell中的动态列表理解

Haskell中的动态列表理解,haskell,Haskell,假设我有一个列表理解,它返回一个序列列表,其中选择的元素相互依赖(参见下面的示例)。是否有一种方法(方便地)根据早期计算对元素数量及其相关条件进行编程?例如,返回类型[[a,b,c]]或[[a,b,c,d,e]],取决于程序中的另一个值?此外,有没有其他/更好的方法比列表理解来阐述相同的想法 (我认为有可能,尽管繁琐且有限,但首先要写出一个更大的列表理解,并通过在s中添加一个参数和辅助函数对其进行修剪,使一个或多个元素成为一个以后可以轻松过滤的值,默认情况下相关条件为真。) s=[[a,b,c,

假设我有一个列表理解,它返回一个序列列表,其中选择的元素相互依赖(参见下面的示例)。是否有一种方法(方便地)根据早期计算对元素数量及其相关条件进行编程?例如,返回类型[[a,b,c]]或[[a,b,c,d,e]],取决于程序中的另一个值?此外,有没有其他/更好的方法比列表理解来阐述相同的想法

(我认为有可能,尽管繁琐且有限,但首先要写出一个更大的列表理解,并通过在s中添加一个参数和辅助函数对其进行修剪,使一个或多个元素成为一个以后可以轻松过滤的值,默认情况下相关条件为真。)

s=[[a,b,c,d]| a
是否有一种方法可以(方便地)基于早期计算对元素数量及其相关条件进行编程?例如,返回类型[[a,b,c]]或[[a,b,c,d,e]],取决于程序中的另一个值

我想您想在类型签名中静态地编码列表(或向量)的长度。不能在类型级别检查标准列表的长度

要做到这一点,需要使用并引入将编码不同大小的虚拟数据类型:

newtype Vector d = Vector { vecArray :: UArray Int Float }

-- using EmptyDataDecls extension too
data D1
data D2
data D3
现在,您可以创建具有不同类型的不同长度的向量:

vector2d :: Float -> Float -> Vector D2
vector2d x y = Vector $ listArray (1,2) [x,y]

vector3d :: Float -> Float -> Float -> Vector D3
vector3d x y z = Vector $ listArray (1,3) [x,y,z]

如果输出的长度取决于输入的长度,那么考虑使用参数化输出。 你可以通过谷歌搜索“Haskell静态大小的向量”找到更多信息


一个更简单的解决方案是使用固定长度的元组。如果您的函数可以生成3元组或5元组,请使用
other
数据类型包装它们:`other(A,b,c)(A,b,c,d,e)。

这个问题非常难以理解

是否有一种方法(方便地)根据早期计算对元素数量及其相关条件进行编程

问题是“program”在这句话中并不是一个可以理解的动词,因为一个人给电脑编程,或者给录像机编程,但你不能“编程一个数字”。所以我不明白你在这里想说什么

但是我可以给你代码回顾,也许通过代码回顾我可以理解你所问的问题

主动代码审查 听起来你可能想通过消除死角来解决迷宫

您的代码实际做的是:

  • 生成一个非死端或与死端相邻的单元格列表,称为
    filtered

  • 从步骤1,
    序列

  • 将四个这样的相邻序列连接成一条路由

  • Major问题:只有当正确的路线正好有八个瓷砖长时,这才有效!尝试解决此迷宫:

    [E]-[ ]-[ ]-[ ] | [ ]-[ ]-[ ]-[ ] | [ ]-[ ]-[ ]-[ ] | [ ]-[ ]-[ ]-[ ] | [ ]-[ ]-[ ]-[E] 相当于,

    someCondition a
    
    (someCondition a == True) == True
    
    因此也相当于,

    someCondition a
    
    (someCondition a == True) == True
    
    或者

    或者

    第一个是
    someconditiona
    ,很好

    关于
    do
    符号的脚注 上例中的
    do
    符号相当于列表理解

    do neighbor <- maze end
       guard (neighbor `notElem` path)
       solve' path' neighbor
    

    do neighbor看起来您正试图通过从有限域中进行唯一选择来解决一些逻辑难题。请参考以下内容:

    这对我们有帮助的方式是,我们在挑选域名时会随身携带域名;而下一个挑选是从狭窄的域名中挑选出来的,其中包含了前一个挑选后剩下的内容,因此自然形成了一条链

    p43 = sum [ fromDigits [v0,v1,v2,v3,v4,v5,v6,v7,v8,v9]
                | (dom5,v5) <- one_of [0,5] [0..9]   -- [0..9] is the
                , (dom6,v6) <- pick_any dom5         --   initial domain
                , (dom7,v7) <- pick_any dom6          
                , rem (100*d5+10*d6+d7) 11 == 0 
                ....
    
    -- all possibilities of picking one elt from a domain
    pick_any :: [a] -> [([a], a)]
    pick_any []     = [] 
    pick_any (x:xs) = (xs,x) : [ (x:dom,y) | (dom,y) <- pick_any xs]
    
    -- all possibilities of picking one of provided elts from a domain
    --                           (assume unique domains, i.e. no repetitions)
    one_of :: (Eq a) => [a] -> [a] -> [([a], a)]
    one_of ns xs = [ (ys,y) | let choices = pick_any xs, n <- ns,
                              (ys,y) <- take 1 $ filter ((==n).snd) choices ]
    
    p43=sum[fromdights[v0,v1,v2,v3,v4,v5,v6,v7,v8,v9]
    |(dom5,v5)[([a],a]
    一个ns-xs=[(ys,y)|让选择=选择你拥有的任何x,n

    你可以用单子形式写下你的理解列表(见):

    (说明:monad必须是支持失败的实例

    guard False
    使monad计算失败为mzero.,随后的结果为列表monad追加mplus=(++)

    import Control.Monad(守卫)
    myDomain=[1..9]--或者其他什么
    有效组合::[a]->[[a]]
    ValidCompositions domainList=do
    康比
    警卫(物业a和物业b)
    返回组合
    [a,b,c]->do
    警卫(物业a和物业b和物业c)
    返回组合
    _->防伪
    main=do
    表单(有效组合myDomain)打印
    
    再次更新,递归获取元素,保存组合和检查

    import Control.Monad
    
    validCombinations :: Eq a => Int -> Int -> [a] -> [(a -> Bool)] -> [a] -> [[a]]
    validCombinations indx size domainList propList accum = do
    
        elt <- domainList   -- try all domain elements
    
        let prop = propList!!indx
        guard $ prop elt               -- some property
        guard $ elt `notElem` accum    -- not repeated 
    
        {-
        case accum of
            prevElt : _ -> guard $ some_combined_check_with_previous elt prevElt
            _ -> guard True
            -}
    
        if size > 1 then do
             -- append recursively subsequent positions
    
             other <- validCombinations (indx+1) (size-1) domainList propList (elt : accum)
    
             return $ elt : other
        else
             return [elt]
    
    myDomain = [1..3] :: [Int]
    
    myProps = repeat (>1)
    
    main = do
               forM_ (validCombinations 0 size myDomain myProps []) print 
       where
          size = 2 
    
    import-Control.Monad
    有效组合::Eq a=>Int->Int->[a]->[(a->Bool)]->[a]->[a]]
    ValidCompositions indx大小域列表属性列表accum=do
    elt guard$some_与上一次elt prevElt的检查相结合
    _->保护正确
    -}
    如果大小>1,则执行此操作
    --递归附加后续位置
    其他(1)
    main=do
    表单(有效组合0大小myDomain myProps[])打印
    哪里
    尺寸=2
    
    大小2的结果具有非平凡的结果:

    [2,3] [3,2] [2,3] [3,2]
    你能发布你的实际代码吗?@krshekhar:原始格式是正确的。@DietrichEpp…当然,它在这里:…它计算序列来解迷宫,但路径的长度是基于另一个计算。旁注:不要写
    someCondition a==True
    ,只写
    someCondition a
    。类似地,
    不写(条件b)
    而不是
    someCondition b==False
    。这样更容易阅读。@DietrichEpp抱歉我没有理解这一点……感谢您花时间阅读我的代码,并解释如何将符号等同于列表理解。这是一个非常简洁的递归迷宫解算器示例!您能告诉我如何实现吗它?我尝试传递不同的参数来开始(有或没有特定的“结束”),但收到了
    [result | neighbor <- maze end,
              neighbor `notElem` path,
              result <- solve' path' neighbor]
    
    p43 = sum [ fromDigits [v0,v1,v2,v3,v4,v5,v6,v7,v8,v9]
                | (dom5,v5) <- one_of [0,5] [0..9]   -- [0..9] is the
                , (dom6,v6) <- pick_any dom5         --   initial domain
                , (dom7,v7) <- pick_any dom6          
                , rem (100*d5+10*d6+d7) 11 == 0 
                ....
    
    -- all possibilities of picking one elt from a domain
    pick_any :: [a] -> [([a], a)]
    pick_any []     = [] 
    pick_any (x:xs) = (xs,x) : [ (x:dom,y) | (dom,y) <- pick_any xs]
    
    -- all possibilities of picking one of provided elts from a domain
    --                           (assume unique domains, i.e. no repetitions)
    one_of :: (Eq a) => [a] -> [a] -> [([a], a)]
    one_of ns xs = [ (ys,y) | let choices = pick_any xs, n <- ns,
                              (ys,y) <- take 1 $ filter ((==n).snd) choices ]
    
    s = [answer | a <- .... , let answer=[....] , length answer==4 ]
    
    s = [answer | a <- .... , let answer=if condition then [a,b,c] else [a]]
    
    import Control.Monad (guard)
    
    myDomain = [1..9]   -- or whatever
    
    validCombinations :: [a] -> [[a]]
    validCombinations domainList = do
            combi <- List.subsequences domainList
            case combi of
                    [a,b] -> do
                            guard (propertyA a && propertyB b)
                            return combi
    
                    [a,b,c] -> do
                            guard (propertyA a && propertyB b && propertyC c)
                            return combi
    
                    _ -> guard False
    
    main = do
             forM_ (validCombinations myDomain) print
    
    import Control.Monad
    
    validCombinations :: Eq a => Int -> Int -> [a] -> [(a -> Bool)] -> [a] -> [[a]]
    validCombinations indx size domainList propList accum = do
    
        elt <- domainList   -- try all domain elements
    
        let prop = propList!!indx
        guard $ prop elt               -- some property
        guard $ elt `notElem` accum    -- not repeated 
    
        {-
        case accum of
            prevElt : _ -> guard $ some_combined_check_with_previous elt prevElt
            _ -> guard True
            -}
    
        if size > 1 then do
             -- append recursively subsequent positions
    
             other <- validCombinations (indx+1) (size-1) domainList propList (elt : accum)
    
             return $ elt : other
        else
             return [elt]
    
    myDomain = [1..3] :: [Int]
    
    myProps = repeat (>1)
    
    main = do
               forM_ (validCombinations 0 size myDomain myProps []) print 
       where
          size = 2 
    
    [2,3] [3,2]