2014-01-08 4 views
8

бесформенного Я пытаюсь написать функцию, что она принимает два HLists l1 и l2 произвольной длины, которые проявляют следующие свойства:В бесформенном, есть два список таким образом, что одна содержат классы типов из другой

  1. Длина l1 и l2 являются одинаковыми
  2. l2 содержит точные типы l1, завернутые в постоянном конструктора внешнего типа.

Так что, если l1 был

1 :: 1.2 :: "hello" :: HNil` 

l2 может быть

Ordering[Int] :: Ordering[Double] :: Ordering[String] :: HNil 

Использование UnaryTCConstraint и LengthAux позволяет мне ограничить длину и требуется статический внешний конструктор для l2, однако наличие их Соответствие стало проблемой.

Любые идеи о том, как я могу это сделать?

+0

Вместо того, чтобы думать о нем как о типах стилей, то, что вы действительно хотите, это тип 'All' (кража из номенклатуры Agda), который принимает тип вида' * -> * '(« предикат »по типам;' Ordering 'в вашем случае) и' HList'. Я могу написать его в чистом Scala, но я уверен, что есть бесформенный способ сделать это, поэтому я буду ждать, пока кто-то еще появится с этим. –

+0

Это нехорошее решение, но как доказательство концепции: [ссылка на pastebin] (http://pastebin.com/1KmuvHJJ). – senia

+0

@senia: На самом деле это не было бы плохим решением, если «Mapped» не существовало. –

ответ

9

Mapped обеспечивает именно это ограничение без дополнительной необходимости для Length. От the documentation:

Тип класс свидетели того, что результат упаковки каждого элемента HListL в конструкторе типа F является Out.

Вот как это выглядит в 1.2.4:

import shapeless._ 

def foo[L1 <: HList, L2 <: HList](l1: L1, l2: L2)(implicit 
    ev: MappedAux[L1, Ordering, L2] 
) =() 

val l1 = 1 :: 1.2 :: "hello" :: HNil 
val l2 = Ordering[Int] :: Ordering[Double] :: Ordering[String] :: HNil 
val l3 = Ordering[Int] :: Ordering[Double] :: Ordering[Char] :: HNil 

И потом:

scala> foo(l1, l2) 

scala> foo(l1, l3) 
<console>:17: error: could not find implicit value for parameter ev: ... 

Как и следовало ожидать. Для 2.0 просто добавьте shapeless.ops.hlist._ импорт и замените MappedAux на Mapped.Aux, и вы готовы к работе.

+0

Красивая, это именно то, что я искал. Спасибо! – Refefer

Смежные вопросы