I реализованы датчики в Haskell следующим образом:преобразователи в Haskell и ограничение -мономорфизм
{-# LANGUAGE RankNTypes #-}
import Prelude hiding (foldr)
import Data.Foldable
type Reducer b a = a -> b -> b
type Transducer a b = forall t. Reducer t b -> Reducer t a
class Foldable c => Collection c where
insert :: a -> c a -> c a
empty :: c a
reduce :: Collection c => Transducer a b -> c a -> c b
reduce f = foldr (f insert) empty
mapping :: (a -> b) -> Transducer a b
mapping f g x = g (f x)
Теперь я хочу, чтобы определить общий map
функцию. Поэтому я загружаю выше код в GHCi:
Prelude> :load Transducer
[1 of 1] Compiling Main (Transducer.hs, interpreted)
Ok, modules loaded: Main.
*Main> let map = reduce . mapping
<interactive>:3:20:
Couldn't match type ‘Reducer t0 b1 -> Reducer t0 a1’
with ‘forall t. Reducer t b -> Reducer t a’
Expected type: (a1 -> b1) -> Transducer a b
Actual type: (a1 -> b1) -> Reducer t0 b1 -> Reducer t0 a1
Relevant bindings include
map :: (a1 -> b1) -> c a -> c b (bound at <interactive>:3:5)
In the second argument of ‘(.)’, namely ‘mapping’
In the expression: reduce . mapping
*Main> let map f = reduce (mapping f)
*Main> :t map
map :: Collection c => (a -> b) -> c a -> c b
Так что я не могу определить map = reduce . mapping
. Однако я могу определить map f = reduce (mapping f)
.
Я считаю, что эта проблема вызвана ограничением мономорфизма. Я бы очень хотел написать map = reduce . mapping
вместо map f = reduce (mapping f)
. Следовательно, у меня есть два вопроса:
- В чем причина этой проблемы? Действительно ли это ограничение мономорфизма?
- Как исправить эту проблему?
Это из-за вывода типа с более высокими рангами. Ограничение мономорфизма здесь не имеет значения. Полагаю, нет легкого исправления, кроме добавления аннотации типа или перехода к точному определению. – chi
Аннотации типа не помогают: 'let map :: Collection c => (a -> b) -> c a -> c b; map f = reduce (отображение f) 'все равно производит ту же ошибку. –
Ошибка типа говорит вам, в чем проблема. Тип 'mapping' заменяется молча, чтобы переместить' forall' в левую часть (try ': t mapping'). Это допустимое (семантико-сохраняющее) преобразование, но typechecker ожидает тип 'Transducer a b', а не' Reducer t a -> Reducer t b' (который * может * быть разными типами). Но когда вы пишете 'reduce (mapping f)', typechecker видит, что приложение 'mapping f' должно иметь тип' forall t. Редуктор t b -> Редуктор t a', который является правильным типом для аргумента 'reduce'. – user2407038