Size: a a a

2021 March 23

AA

A64m AL256m qn<co... in Haskell
почему?
источник

IO

I O in Haskell
Sooqa
type family RecurseAndCheck a b where
  RecurseAndCheck a (HList '[]) = CSat
  RecurseAndCheck a (HList ((l :: a) : b)) = RecurseAndCheck a (HList b)
  RecurseAndCheck a (HList ((k :: r) : b)) = CNSat
class (forall t (a :: HList t) . RecurseAndCheck (Pair Symbol *) a)
  => Record a

можно это заставить работать?
Вы же вроде справшивали про это в багтрекере ghc, вам там правильно сказали что элементы хлиста всегда кайнда Type, a (Symbol, Type) /= Type. Так что проверять что элементы хлиста имеют кайнд (Symbol, Type) бессмысленно - точно не имеют.

Чтобы сделать рекорд на хлистe вы можете объявить ньютайп

newtype Field (name :: Symbol) typ = Field typ

и считать рекордом такой хлист, у которого все типы элементов вида Field _ _ (кайнда Type) . Проверять тогда можно как-то так:

type family Check ts where
 Check (HList '[])           = () :: Constraint
 Check (HList (Field _ _:r)) = Check (HList r)
 Check (HList (t:_))         = TypeError ('Text "Non-Field type in record: " ':<>: 'ShowType t)

class Check ts => Record ts
instance Check ts => Record ts

Но лучше конечно сделать как Adam Gundry написал, что-нибудь типа

data Record ts where
 RNil :: Record '[]
 (:>) :: x -> Record xs -> Record ('(name, x) : xs)

Тогда у вас Record является рекордом by construction, никаких проверок не нужно. См. parse, not validate.

Или, если вы все-таки хотите сделать на хлисте, например чтобы рекорд можно было использовать как хлист, можно взять более общий хлист параметризованный типом f:

-- Data.SOP.NP из sop-core, NP Identity ~= HList
data NP f xs where
 Nil  :: NP f '[]
 (:*) :: f x -> NP f xs -> NP f (x:xs)
infixr 5 :*

type Snd :: (a, b) -> b
type family Snd t where
 Snd '(_, b) = b

newtype Field nt = Field (Snd nt)

type Record = NP Field

foo :: Record [ '("foo", Bool), '("bar", Int) ]
foo = Field True :* Field 1 :* Nil
источник

S

Sooqa in Haskell
I O
Вы же вроде справшивали про это в багтрекере ghc, вам там правильно сказали что элементы хлиста всегда кайнда Type, a (Symbol, Type) /= Type. Так что проверять что элементы хлиста имеют кайнд (Symbol, Type) бессмысленно - точно не имеют.

Чтобы сделать рекорд на хлистe вы можете объявить ньютайп

newtype Field (name :: Symbol) typ = Field typ

и считать рекордом такой хлист, у которого все типы элементов вида Field _ _ (кайнда Type) . Проверять тогда можно как-то так:

type family Check ts where
 Check (HList '[])           = () :: Constraint
 Check (HList (Field _ _:r)) = Check (HList r)
 Check (HList (t:_))         = TypeError ('Text "Non-Field type in record: " ':<>: 'ShowType t)

class Check ts => Record ts
instance Check ts => Record ts

Но лучше конечно сделать как Adam Gundry написал, что-нибудь типа

data Record ts where
 RNil :: Record '[]
 (:>) :: x -> Record xs -> Record ('(name, x) : xs)

Тогда у вас Record является рекордом by construction, никаких проверок не нужно. См. parse, not validate.

Или, если вы все-таки хотите сделать на хлисте, например чтобы рекорд можно было использовать как хлист, можно взять более общий хлист параметризованный типом f:

-- Data.SOP.NP из sop-core, NP Identity ~= HList
data NP f xs where
 Nil  :: NP f '[]
 (:*) :: f x -> NP f xs -> NP f (x:xs)
infixr 5 :*

type Snd :: (a, b) -> b
type family Snd t where
 Snd '(_, b) = b

newtype Field nt = Field (Snd nt)

type Record = NP Field

foo :: Record [ '("foo", Bool), '("bar", Int) ]
foo = Field True :* Field 1 :* Nil
А сделать общую версию Check возможно? Не хочется писать под каждый кейс.

И ещё смежный вопросик - почему стринги не лифтятся автоматом, как это делают числа ?
источник

S

Sooqa in Haskell
Не знаю как более точно описать, но почему у значений * нельзя проверять кайнд? Напр у Either Int String это *, но это ещё и просто Either.
источник

IO

I O in Haskell
Обобщенную Check в смысле higher order function All, чтобы использовать как All IsField? В принципе возможно, но нужна дефункциализация, нативных hof на уровне типов нет. Посмотрите например https://blog.poisson.chat/posts/2018-08-06-one-type-family.html, https://hackage.haskell.org/package/first-class-families
источник

ЗП

Зигохистоморфный Пре... in Haskell
I O
Обобщенную Check в смысле higher order function All, чтобы использовать как All IsField? В принципе возможно, но нужна дефункциализация, нативных hof на уровне типов нет. Посмотрите например https://blog.poisson.chat/posts/2018-08-06-one-type-family.html, https://hackage.haskell.org/package/first-class-families
я на этом тайплевел рексхемы написал)
источник

IO

I O in Haskell
Я помню тайплевел линзы на синглтонах делали)
источник

IO

I O in Haskell
> И ещё смежный вопросик - почему стринги не лифтятся автоматом, как это делают числа ?

Не распарсил, что значит лифтятся?
источник

JS

Jerzy Syrowiecki in Haskell
вроде так же лифтятся, как и числа
источник

IO

I O in Haskell
Промоутятся всм? Вроде бы да, так же
источник

ЗП

Зигохистоморфный Пре... in Haskell
все оно работает
Prelude> :t "Test"
"Test" :: [Char]
Prelude> :kind! "Test"
"Test" :: GHC.Types.Symbol
= "Test"
источник

S

Sooqa in Haskell
I O
Обобщенную Check в смысле higher order function All, чтобы использовать как All IsField? В принципе возможно, но нужна дефункциализация, нативных hof на уровне типов нет. Посмотрите например https://blog.poisson.chat/posts/2018-08-06-one-type-family.html, https://hackage.haskell.org/package/first-class-families
Ясно, спс
источник

к

кана in Haskell
Переслано от кана
https://hackage.haskell.org/package/recover-rtti-0.3.0.0

смотрите какая классная штука
источник

S

Sooqa in Haskell
а оно умеет так?
▢ : ✶ ?
источник

ЗП

Зигохистоморфный Пре... in Haskell
как им пользоваться?
источник

к

кана in Haskell
> data X = X
> data Y = Y X X
> Debug.RecoverRTTI.anythingToString (Y X X)
"Y X X"

> Debug.RecoverRTTI.anythingToString (1, \x -> x)
"(1,<Fun>)"
источник

ЗП

Зигохистоморфный Пре... in Haskell
источник

к

кана in Haskell
ого, это тоже круто
источник

ЗП

Зигохистоморфный Пре... in Haskell
можно через явный forall как-то от Proxy избавиться?
type (~>) f g = Proxy f -> Proxy g -> Type
источник

к

кана in Haskell
type f ~> g = forall a. f a -> g a
?
источник