let
не делает ничего, кроме определения нового символа, который принимает одно заданное значение. Вы всегда можете просто вставить определение вручную:
[ y | x <- xs, let y = [x,x] ] ≡ [ [x,x] | x <- xs ]
Таким образом, любое такое выражение только с одним <-
имеет форму
[ f x | x<-xs ]
что эквивалентно map f xs
. Таким образом, список результатов всегда должен иметь ту же длину, что и xs
, что делает невозможным достижение желаемого поведения duplicate
: если вы хотите иметь дубликаты, вам нужно инкапсулировать их как внутренние списки, чтобы они не считались дополнительными элементами.
Чтобы объединить эти вложенные списки обратно в «плоский», вы можете использовать тот факт, что списки являются монадами:
join :: Monad m => m (m a) -> m a
Прелюдия Control.Monad> присоединиться к [[1,1], [2,2]]
[1,1,2,2]
На самом деле join
— это то, как теоретики категорий предпочитают определять монады, но, как вы, возможно, знаете, Haskell делает это немного по-другому:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
a >>= f = join (fmap f a)
или, как это фактически определяется наоборот,
join a = a >>= id
Поместите это в модифицированную let
версию duplicate
:
join [y | x <- xs, let y = [x,x] ]
≡ [y | x <- xs, let y = [x,x] ] >>= id
≡ map (\x -> [x,x]) xs >>= id
≡ xs >>= id . (\x -> [x,x])
≡ xs >>= (\x -> [x,x])
≡ do { x<-xs; [x,x] }
≡ do { x<-xs; y<-[x,x]; return y } -- by the monad laws
Итак, выражение do { a<-p; b<-q; ... return x }
— это включение монады, обобщение спискового включения. Его можно переписать [x | a<-q, b<-q, ...]
. Для нашей проблемы,
join [y | x <- xs, let y = [x,x] ] ≡ [y | x<-xs, y<-[x,x]]
где вы начали. Использование двух <-
неизбежно при использовании чистого понимания списка.
Конечно, вы все еще можете использовать также let в любой момент...
[y | x<-xs, y<-[x,x]]
≡ [y | x<-xs, let z=[x,x], y<-z]
≡ [a | x<-xs, let z=[x,x], y<-z, let a=y]
≡ [a | x<-xs, let z=let w=[let q=x in q, let r=x in r] in w, y<-z, let a=y]
≡ ...
person
leftaroundabout
schedule
21.09.2013
[y | x <- xs, let y = [x,x]]
==[[x,x] | x <- xs]
видишь ли, это не то, что ты хотел - person Sassa NF   schedule 22.09.2013