2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Haskell: как параметризовать тип целым числом?
Сообщение19.02.2017, 11:42 
Заслуженный участник


02/08/11
7059
Допустим, есть библиотека матриц произвольной размерности (https://hackage.haskell.org/package/matrix-0.3.5.0/docs/Data-Matrix.html#g:3).
И я хочу дефинировать, что матрицы одинаковой размерности образуют группу по сложению (http://hackage.haskell.org/package/vector-space-0.10.4/docs/Data-AdditiveGroup.html#t:AdditiveGroup).

Попробуем:
Используется синтаксис Haskell
instance AdditiveGroup a => AdditiveGroup (Matrix a) where
  zeroV = ???


Мы должны создать нулевую матрицу, но мы не знаем какой размерности!

Конечно, можно создать специальные типы MD1x1, MD1x2, MD2x1, MD2x2, ... и использовать их как параметры, и тогда всё получится, но я не верю, что, учитывая мощные возможности GHC (такие как TemplateHaskell и т. п.), нельзя сделать более красиво.

Есть идеи?

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение19.02.2017, 12:45 
Заслуженный участник
Аватара пользователя


06/10/08
6422
В современных версиях GHC есть такие возможности (расширение DataKinds, модули GHC.TypeLits, Data.Proxy).

Вот пример использования, похожий на то, что Вам надо: https://github.com/fhaust/aer-utils/blo ... mpleMat.hs

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение19.02.2017, 12:48 
Заслуженный участник


02/08/11
7059
Xaositect, спасибо, это действительно то, что надо.

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение19.02.2017, 14:31 
Заслуженный участник


02/08/11
7059
Почему-то не получается:
Используется синтаксис Haskell
newtype Mat (r :: Nat) (c :: Nat) a = Mat (Matrix a)

mrows :: forall r c a . KnownNat r => Mat r c a -> Int
mrows _ = fromInteger $ natVal (Proxy :: Proxy r)
 


Ответ компилятора:
  1. • Couldn't match kind ‘*’ with ‘Nat’ 
  2.   When matching the kind of ‘Proxy’ 
  3. • In the first argument of ‘natVal’, namely ‘(Proxy :: Proxy r)’ 
  4.   In the second argument of ‘($)’, namely ‘natVal (Proxy :: Proxy r)’ 
  5.   In the expression: fromInteger $ natVal (Proxy :: Proxy r) 

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение19.02.2017, 14:42 
Заслуженный участник
Аватара пользователя


06/10/08
6422
GHC не знает, что r в теле функции - это то же самое r, что и в объявлении типа. Нужно расширение ScopedTypeVariables.

Используется синтаксис Haskell
{-# LANGUAGE DataKinds, KindSignatures, ScopedTypeVariables, Rank2Types #-}

module Temp where

import GHC.TypeLits
import Data.Proxy

type Matrix a = [[a]]

newtype Mat (r :: Nat) (c :: Nat) a = Mat (Matrix a)

mrows :: forall r c a. KnownNat r => Mat r c a -> Int
mrows _ = fromInteger $ natVal (Proxy :: Proxy r)
 

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение19.02.2017, 14:57 
Заслуженный участник


02/08/11
7059
Xaositect, да, точно. Спасибо ещё раз, вроде получилось (во всяком случае скомпилировалось.

(Мне очень нравится Haskell, но этот ЯП не просто умнее меня, а просто страшно представить насколько умнее.)

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение21.02.2017, 00:02 


05/09/12
2587
На правах дилетанта позволите уточнить пару вопросов?

1) Вы предусматриваете каким-либо образом на этапе компиляции контроль одинаковых размерностей матриц при операциях с ними? Без создания своих типов для каждой размерности.

2) Если нет, то почему бы не выбрать в качестве нейтрального элемента просто бесконечный по всем измерениям тип, который участвует в операциях с элементами того же типа любых размерностей? С двумерными матрицами сложнее, возьмем одномерные вектора нефиксированной длины. Группу по сложению не стал рисовать, но на примере моноида идея видна:

Используется синтаксис Haskell
import Data.Monoid

newtype Vec a = Vec [a] deriving Show

instance Monoid a => Monoid (Vec a) where
    mempty = Vec $ repeat mempty  
    Vec a `mappend` Vec b = Vec $ zipWith mappend a b

main = print $ Vec (map Sum [1..3]) <> Vec (map Sum [10..])

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение21.02.2017, 00:19 
Заслуженный участник


27/04/09
28128
_Ivana в сообщении #1194230 писал(а):
1) Вы предусматриваете каким-либо образом на этапе компиляции контроль одинаковых размерностей матриц при операциях с ними? Без создания своих типов для каждой размерности.
Да, тут это вроде как раз и происходит. Один тип с киндом Nat -> Nat -> * -> *, после применения типов-размерностей и типа значений элементов матриц остаётся *, тип со значениями.

 Профиль  
                  
 
 Re: Haskell: как параметризовать тип целым числом?
Сообщение21.02.2017, 00:23 


05/09/12
2587
arseniiv спасибо, понятно. Тогда отзываю предложенную халтуру :-)

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: granit201z


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group