ja mucking z bezpłatnych monad i obiektyw, korzystając z bezpłatnego monady stworzyć własną wersję monady IO:trudności z zoomem i wolnych monad
data MyIO next
= LogMsg String next
| GetInput (String -> next)
deriving (Functor)
jestem układania to na szczycie monady państwowej tak: FreeT MyIO (State GameState) a
gdzie GameState
jest:
data GameState = GameState { _players :: [PlayerState] }
teraz, co chciałbym mieć to sposób na "zoom-do" a PlayerState
od kontekstu GameState
. Coś takiego:
zoomPlayer :: Int -> FreeT MyIO (State PlayerState) a -> FreeT MyIO (State GameState) a
zoomPlayer i prog = hoistFreeT (zoom (players . element i)) prog
Ale ja dostaję ten błąd:
No instance for (Data.Monoid.Monoid a1)
arising from a use of ‘_head’
Błąd ten wydaje się mieć związek z faktem, że players . element i
jest przechodzenie; jeśli usunę ten aspekt listy z _players
i użyję zwykłego obiektywu, wtedy kod działa.
Wszelkie pomysły na temat napisania tej funkcji?
Czy nie byłoby łatwiej zamiast tego mieć 'StateT GameState (Free MyIO) a'? Jeśli chcesz później zamienić 'Free MyIO' na' IO', to będzie to zwykły sposób, ponieważ nie ma wersji transformatora 'IO'. – bheklilr
Problem wynika również z faktu, że indeksowanie listy nie jest bezpieczną operacją. Biblioteka obiektywów chce, abyś zwrócił typ, który może być ustawiony domyślnie, a standardową czcionką jest "Monoid". Jeśli po prostu dodasz 'Monoid a =>' do sygnatury typu 'zoomPlayer', to zostaniesz ustawiony. To ogranicza oczywiście to, co możesz zwrócić, ale będziesz musiał, chyba że chcesz napisać więcej kodu. – bheklilr
@bheklir Mój zły, "a" w błędzie był literówka; faktycznie było to "a1". Przepraszam za zamieszanie. Wygląda na to, że 'FreeF' jest tym, czego oczekuje się od monoidu, ale nie mam sposobu na napisanie takiej instancji. Może mógłbym tymczasowo zawinąć ją na listę, a następnie ją rozwinąć. – Pubby