Ошибка Вывод типа Kotlin не удалось Ожидаемое несоответствие типов Картаожидалось - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь манипулировать структурой данных, чтобы передать ее этой функции fun handleRequests(messages: Map<MessageDestination, List<MessageSender>>): Either<Errors.RequestError, Unit>.Но я продолжаю получать эту ошибку: синтаксическая ошибка

Error:(27, 63) Kotlin: Type inference failed. Expected type mismatch: inferred type is Map<MessageDestination, List<Pair<MessageSender, String>>> but Map<MessageDestination, List<MessageSender>> was expected.

Мне нужно преобразовать мои данные в Map<MessageDestination, List<MessageSender>>, но я не знаю, как это сделать.Вот код:

package testp.package1.handlers

import arrow.core.Either
import arrow.core.flatMap
import com.amazonaws.services.lambda.runtime.Context
import com.amazonaws.services.lambda.runtime.RequestHandler

interface InterfaceService {
    fun handleRequests(messages: Map<MessageDestination, List<MessageSender>>): Either<Errors.RequestError, Unit>
}

abstract class AbstractMessageHandler(
        override val service: InterfaceService =
                ServiceImpl()) : MessageHandler<MyMessage>() {

    abstract val emailType: ServiceImpl.Companion.EmailType
    override val emailParser: IMessageParser<MyMessage> = M2MessageParser()

    override fun handle(event: List<String>): Either<Errors.RequestError, Pair<List<Errors.RequestError>, Int>> =
            emailParser.parseEmails(event)
                    .map { (error, messages) ->
                        error to messages.map { myMessage ->
                            MessageSender(message = myMessage.environment) to myMessage.emailAdrress
                        }
                    }
                    .flatMap { (errors: List<Errors.RequestError>, emailMesssages: List<Pair<MessageSender, String>>) ->
                        service.handleRequests(emailMesssages.groupBy { MessageDestination(it.second) }).map {
                            Pair(errors, emailMesssages.size)
                        }
                    }
}

data class MessageDestination(val emailAddress: String)
data class MyMessage(val environment: String, val emailAdrress: String, val phoneId: String)
data class MessageSender(val message: String)


class ServiceImpl : InterfaceService {
    override fun handleRequests(messages: Map<MessageDestination, List<MessageSender>>): Either<Errors.RequestError, Unit> {
        TODO("logic goes her")
    }
    companion object {
        enum class EmailType {
            M1, M2
        }
    }
}

object Errors {
    interface RequestError {
        val message: String
    }
    data class UnexpectedError(override val message: String) : RequestError
}

1 Ответ

0 голосов
/ 04 октября 2018

TL; DR: Требуется преобразовать значения, сгруппированные в списке, поэтому:

emailMesssages.groupBy( 
    { MessageDestination(it.second) },
    { it.first }
)

Длинная версия:

Итак, вы начинаете с: emailMesssages: List<Pair<MessageSender, String>> и хотите преобразовать его в тип Map<MessageDestination, List<MessageSender>>

Вы пытаетесь добиться этого с помощью emailMesssages.groupBy { MessageDestination(it.second) }.Что groupBy группирует элементы из списка по указанному вами ключу.Важно то, что он объединяет все элементы (в данном случае все Pair с) для одного ключа в список .

Так что если у вас есть (пример из официальных документов ):

val words = listOf("a", "abc", "ab", "def", "bc")
val byLength = words.groupBy { it.length }

тогда byLength равно:

1 -> listOf("a")
2 -> listOf("ab", "bc")
3 -> listOf("abc", "def")

Это объясняет, почему у вас есть тип Map<MessageDestination, List<Pair<MessageSender, String>>> вместо Map<MessageDestination, List<MessageSender>>.

То, что вы хотите не нужно группировать элементы из списка , вы хотите группировать преобразованные значения из элементов списка .

По сути, вам нужен еще один вариант 'groupBy' с keySelector AND valueTransform:

inline fun <T, K, V> Array<out T>.groupBy(
    keySelector: (T) -> K,
    valueTransform: (T) -> V
): Map<K, List<V>> (source)`

в вашем случае это будет выглядеть так:

emailMesssages.groupBy( 
    { MessageDestination(it.second) },
    { it.first }
)
...