ошибка сопоставления типов. что вызвало это и как это решить - PullRequest
0 голосов
/ 20 июня 2020
pop :: [Int] -> (Int,[Int])  
pop (x:xs) = (x,xs)  

Я пытаюсь сделать это

ghci> pop [1,2,3,4]
(1,[2,3,4])
ghci> (\(a,b) -> pop b) it
(2,[3,4])

с одной строкой, используя монаду

ghci> pop [1,2,3] >>= (\(a,b) -> pop b)

<interactive>:70:19: error:
    * Couldn't match expected type `[Int]'
                  with actual type `(a0, [Int])'
    * In the pattern: (a, b)
      In the second argument of `(>>=)', namely `(\ (a, b) -> pop b)'
      In the expression: pop [1, 2, 3] >>= (\ (a, b) -> pop b)

, она получает ошибку.

Затем я пытаюсь использовать другой способ, пытаясь выяснить что-нибудь, но с аналогичной проблемой

sf = do 
    a <- pop [1,2,3,4]
    (\(x,y) -> y)-- this line having problem


Couldn't match expected type `(Int, b)'
              with actual type `(a0, [Int]) -> (Int, [Int])'
* The lambda expression `\ (x, y) -> pop y' has one argument,
  but its type `(Int, b)' has none
  In a stmt of a 'do' block: (\ (x, y) -> pop y)
  In the expression:
    do a <- pop [1, 2, ....]
       (\ (x, y) -> pop y)
* Relevant bindings include
sf :: (Int, b)

так есть ли какой-либо способ использовать монаду для записи в одну строку?

1 Ответ

0 голосов
/ 20 июня 2020

Как правило, кортежи не образуют монады, но оператор >>= работает только с Monad.

Что вы можете сделать, так это просто составить, используя вместо этого $:

*Q62478798> (\(a,b) -> pop b) $ pop [1, 2, 3]
(2,[3])

Если вы предпочитаете композицию слева направо, вы можете использовать оператор & из Data.Function:

*Q62478798 Data.Function> pop [1,2,3] & (\(a,b) -> pop b)
(2,[3])

С другой стороны, кортежи do образуют монады, если первый элемент образует моноид, как видно из этого примера:

Monoid a => Monad ((,) a)

Что вы могли бы сделать, так это сначала ослабить тип pop:

pop :: [a] -> (a, [a])
pop (x:xs) = (x,xs)

Это позволяет вам pop из списка любого типа, включая списки моноидальных типов, например:

*Q62478798 Data.Monoid> pop $ fmap Sum [1,2,3]
(Sum {getSum = 1},[Sum {getSum = 2},Sum {getSum = 3}])

Теперь вы можете составлять с Оператор >>=:

*Q62478798 Data.Monoid> (pop $ fmap Sum [1,2,3]) >>= (\xs -> pop xs)
(Sum {getSum = 3},[Sum {getSum = 3}])

или, сокращение эта:

*Q62478798 Data.Monoid> (pop $ fmap Sum [1,2,3]) >>= pop
(Sum {getSum = 3},[Sum {getSum = 3}])

Эта комбинация композиции справа налево и слева направо совершенно нечитаема, так что вы можете использовать & или =<<:

*Q62478798 Data.Monoid> pop =<< (pop $ fmap Sum [1,2,3])
(Sum {getSum = 3},[Sum {getSum = 3}])

Я не знаю, зачем вы это делаете, но вы можете.

...