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