Семейства шрифтов Haskell и фиктивные аргументы

Я сделал функцию подобной numpy's array. Это преобразовывает списки в массивы, списки списков к 2-м массивам, и т.д.

Это работает как это:

ghci> arrFromNestedLists ["hello", "world"] :: Array (Int, (Int, ())) Char
array ((0,(0,())),(1,(4,()))) [((0,(0,())),'h'),((0,(1,())),'e'),((0,(2,())),'l'),((0,(3,())),'l'),((0,(4,())),'o'),((1,(0,())),'w'),((1,(1,())),'o'),((1,(2,())),'r'),((1,(3,())),'l'),((1,(4,())),'d')]

(Int, (Int, ())) и нет (Int, Int) потому что я не знаю о программном способе увеличить длину кортежа. (вопрос о стороне: есть ли такой путь?)

Кодирование его было неловким, и я должен был сделать "обходное решение" (раздающий фиктивные аргументы функциям) для него для работы. Интересно, существует ли лучший путь.

Таким образом, вот код, прерванный деталями ужасных обходных решений:

{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, TypeFamilies #-}

type family ListOfIndex i a
type instance ListOfIndex () a = a
type instance ListOfIndex (Int, i) a = [ListOfIndex i a]

class Ix i => ArrConv i where
  acBounds :: a -> ListOfIndex i a -> (i, i)
  acFlatten :: i -> ListOfIndex i a -> [a]

acBounds "должен" быть :: ListOfIndex i a -> (i, i). И так же для acFlatten. Каждому дают фиктивную переменную (undefined всегда данное значение), потому что иначе я не мог заставить его компилировать :(

arrFromNestedLists :: forall i a. ArrConv i => ListOfIndex i a -> Array i a
arrFromNestedLists lst =
  listArray
  (acBounds (undefined :: a) lst)
  (acFlatten (undefined :: i) lst)

Выше макет undefined передача параметров на работе. Это говорит GHC который экземпляр ListOfIndex использовать.

instance ArrConv () where
  acBounds _ = const ((), ())
  acFlatten _ = (: [])

Ниже функции должен был быть acBounds функция в экземпляре ArrConv, и объявляется снаружи только потому, что я должен использовать ScopedTypeVariables и я не знаю, как я могу сделать это в функции в определении экземпляра..

acSucBounds
  :: forall a i. ArrConv i
  => a -> [ListOfIndex i a] -> ((Int, i), (Int, i))
acSucBounds _ lst =
  ((0, inStart), (length lst - 1, inEnd))
  where
    (inStart, inEnd) = acBounds (undefined :: a) (head lst)

instance ArrConv i => ArrConv (Int, i) where
  acBounds = acSucBounds
  acFlatten _ = concatMap (acFlatten (undefined :: i))
5
задан yairchu 11 January 2010 в 17:35
поделиться

1 ответ

Причина, по которой необходимы дополнительные аргументы ACBounds и AcFlatten, заключается в том, что типы A и I не может быть восстановлено из listOfindex Ia -> (i, i) и listofindex Ia -> [A] соответственно. Один обходной путь состоит в том, чтобы объединить два метода в один метод ACARGS типа ListOfindex I A -> ((i, i), a) . Теперь единственная проблема состоит в том, чтобы использовать его в экземпляре (INT, I) таким образом, что предотвращает обработку TypeChecker от обобщения своего типа, вызывающего одинаковую проблему, что и раньше (например, мы не можем просто использовать FST. Acargs ).

{-# LANGUAGE TypeFamilies, FlexibleInstances #-}

import Data.Array

type family ListOfIndex i a
type instance ListOfIndex () a = a
type instance ListOfIndex (Int, i) a = [ListOfIndex i a]

class Ix i => ArrConv i where
  acArgs :: ListOfIndex i a -> ((i, i), [a])

instance ArrConv () where
  acArgs x = (((), ()), [x])

instance ArrConv i => ArrConv (Int, i) where
  acArgs lst =
    (((0, inStart), (length lst - 1, inEnd)), args >>= snd)
    where
      args = map acArgs lst
      (inStart, inEnd) = fst (head args)

arrFromNestedLists :: ArrConv i => ListOfIndex i a -> Array i a
arrFromNestedLists = uncurry listArray . acArgs
4
ответ дан 15 December 2019 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: