169 похожих чатов

Как доказать компилятору, что (Num a) точно будет, потому что

нет других конструкторов, не записывая это в констрейнты foo?

data A a where
MkA :: Num a => {value :: a} -> A a
foo :: A a -> A a -> A a
foo a b = MkA (value a + value b)

==============================
error:
• No instance for (Num a) arising from a use of ‘MkA’
Possible fix:
add (Num a) to the context of
the type signature for:
foo :: forall a. A a -> A a -> A a
• In the expression: MkA (value a + value b)
In an equation for ‘foo’: foo a b = MkA (value a + value b)

foo a b = MkA (value a + value b)
^^^^^^^^^^^^^^^^^^^^^^^

11 ответов

9 просмотров

Просто не задавать тип для foo. Компилятор как раз знает, что тип будет Num a => A a -> A a -> A a, поэтому ругается на неправильную сигнатуру.

Максим-Б Автор вопроса
Михаил
Просто не задавать тип для foo. Компилятор как раз...

а если усложнить задачу? :) тут сигнатуру убрать нельзя, она в классе написана class C c where foo :: a -> c a data A a where MkA :: Num a => a -> A a instance C A where foo a = MkA a =========================== a.hs:40:13: error: • No instance for (Num a) arising from a use of ‘MkA’ Possible fix: add (Num a) to the context of the type signature for: foo :: forall a. a -> A a • In the expression: MkA a In an equation for ‘foo’: foo a = MkA a In the instance declaration for ‘C A’ | 40 | foo a = MkA a |

Максим Б
а если усложнить задачу? :) тут сигнатуру убрать н...

Тут это уже не работает специально. foo в том виде, в каком вы её описали, должна работать для любого типа, а в случае MkA это не так. Решений два: или добавить Num a в сигнатуру foo, или убрать Num a из определения типа A (действительно ли он там нужен?). Может быть, меня кто-то поправит, указав ещё пути.

Максим-Б Автор вопроса
Михаил
Тут это уже не работает специально. foo в том виде...

я колдую над чуть более сложным примером, там констрейнт для конструктора убрать не получится, имплементация на него завязана при этом у разных типов, для которых я хочу инстансы класса, эти констрейнты разные то есть хочется что-нибудь вроде instance Num a => C (A a) where ... но "a", как здесь, зафиксировать (так можно сказать?) нельзя, потому что тогда по кайндам не проходит - C хочет "* -> *", а у "A a" он просто "*"

Максим Б
я колдую над чуть более сложным примером, там конс...

В этом случае надо изменить foo. Всё-таки ограничения важны в типах, они не для красоты пишутся. Думаю, можно ещё как-то поколдовать с TypeFamilies или MultiParamTypeClasses, чтобы вынести задание Num в другую часть кода. Что-то вроде class Num a => C c a where foo :: a -> c a

Максим Б
посмотрю, спасибо!

{-# LANGUAGE GADTs, MultiParamTypeClasses, FlexibleInstances #-} class C c a where foo :: a -> c a data A a where MkA :: Num a => a -> A a instance Num a => C A a where foo = MkA Но меня всё равно не оставляет ощущение, что проще было бы добавить Num a как ограничение к foo или разобраться, что же на самом деле требуется для A.

Максим-Б Автор вопроса
Михаил
{-# LANGUAGE GADTs, MultiParamTypeClasses, Flexibl...

проще в конкретном случае - конечно :) но может быть, например, библиотечный класс, который менять нельзя интересно разобраться, как такие штуки вообще решают (я ж точно не первый, кто таким вопросом задался) за сниппет спасибо! буду разбираться :)

Максим Б
проще в конкретном случае - конечно :) но может бы...

Там ещё есть хитрость. Или такой класс: class C con c | c -> con where foo :: con a => a -> c a И сделать instance C Num A С типами аналогично. Можно, например, написать: data A n a where MkA :: n a => a -> A n a Правда, в обоих случаях надо не забыть включить нужные расширения.

Максим-Б Автор вопроса
Михаил
Там ещё есть хитрость. Или такой класс: class C co...

вау, втащить констрейнты в параметры я б точно не догадался спасибо огромное!

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

Обсуждают сегодня

Какой-то там пердун в 90-х решил, что есть какая-то разная типизация. Кого вообще это волнует?
КТ315
49
void terminal_scroll() { memmove(terminal_buffer, terminal_buffer + VGA_WIDTH, buffer_size - VGA_WIDTH); memset(terminal_buffer + buffer_size - VGA_WIDTH, 0, VGA_WIDTH); ...
Егор
47
Всем привет! Подскажите, пожалуйста, в чем ошибка? Настраиваю подключение к MySQL. Либы лежат рядом с exe. Все как по "учебнику"
Евгений
16
А можете как-то проверить меня по знаниям по ассемблеру?
A A
132
Здравствуйте! У меня появилась возможность купить книгу "Изучай Haskell во имя добра!". Но я где-то слышал, что эта книга устарела. Насколько это правда??
E
22
Здравствуйте! Я вот на stepic решаю задачи на хаскеле https://stepik.org/lesson/8443/step/8?unit=1578 мой код import Data.List (isInfixOf) removing :: String -> [String] ->...
E
10
Камрады, кто тесно работал с vtv, хотел уточнить. Ширина column задаётся жёстко на этапе создания дерева или можно в рантайме ее менять программно (не мышкой)?
Ed Doc
10
да ладно ... что там неочевидного ? глянуть в исх-ки датасета и/или кверика чтобы понять в каком месте и как выполняется обращения к св-вам blablaSQL - минутное дело, даже е...
Сергей
7
Здесь для arm кто-нибудь кодит ?
Nothing
52
Всем привет, у меня есть сервер принимающий входящие HTTP подключения, как проверить, что подключение было через прокси или нет, есть какие то поля в заголовках по которым мо...
DS
8
Карта сайта