Extracting `a` from Applicative `f a` - haskell

Learn You a Haskell offers the following exercise:
Let's try implementing a function that takes a list of applicatives and
returns an applicative that has a list as its result value.
LYAH gives the type signature sequenceA' :: (Applicative f) => [f a] -> f [a]
I started with Applicative, but wasn't sure how to extract a from f a in a general way for all Applicative's.
So, I implemented it as a Maybe. Of course this is unacceptable for all `Applicative's.
import Control.Applicative
sequenceA' :: (Num a) => [Maybe a] -> Maybe [a]
sequenceA' [] = pure []
sequenceA' xs = pure $ [extract' x | x <- xs ]
extract' :: (Num a) => Maybe a -> a
extract' x = case x of
Just y -> y
Nothing -> 0
How can I extract a from f a where f is an Applicative?

You can't in general. In fact, the Maybe example you gave is a good example of why since it requires it to be a Num instance. It wouldn't make sense for the Maybe Applicative in general, so that would be a counterexample to a general solution. Another counterexample would be IO. There is no valid extract implementation for IO.
To make a function that is general enough to work with all Applicative instances, you must be able to construct the function using only methods from Applicative and its super-class, Functor. There is no way to make extract using only fmap, pure and (<*>).

It's not necessary to take things out of the applicative functor to achieve this.
The great thing about applicative functors is they allow you to use ordinary functions on the results of each applicative computation, so
if you have applicatives c1, c2 and c3 of types f a, f b, f c
that produce values v1, v2 and v3 of types a, b and c,
but you actually want to use a function g :: a -> b -> c -> d on the values
to produce g v1 v2 v3 :: d, then you can do
g <$> c1 <*> c2 <*> c3
which has type f d.
So we can use the function (:) to join the first value out of our list of applicatives with the rest of them, so you can do someytthing like (:) <$> thingThatGivesFirstValue <*> thing that gives the rest of the list. So it'll be a nice recursion if you pattern match on the list of applicatives.
sequenceA' :: (Applicative f) => [f a] -> f [a]
sequenceA' [] = -- just give the empty list
sequenceA' (c:cs) = -- hmm. What could go here then?
so for example you should get
ghci> sequenceA' [getLine, getLine, getLine]
Hello
there
everyone
["Hello","there","everyone"]
ghci> sequenceA' [Just 3, Just 4, Just 5]
Just [3,4,5]
Here's an example function to help you along with the recursice case:
nth :: Applicative f => f Int -> f [a] -> f a
nth wrappedInt wrappedList = (!!) <$> wrappedInt <*> wrappedList
So you don't need to unwrap anything or get values out, the operators<$> and <*> let you do what you like inside.
nth (Just 3) (Just "Hello") == 'l'

Here's a hint:
foo :: Applicative f => f Int -> f Int -> f Int
foo fx fy = (+) <$> fx <*> fy -- apply + "under" the functor
bar :: Applicative f => f a -> f [a] -> f [a]
bar fx fxs = ??? <$> fx <*> fxs -- apply ??? "under" the functor
sequenceA' :: Applicative f => [f a] -> f [a]
sequenceA' [] = pure [] -- as in your solution
sequenceA' (x:xs) = let y = x -- :: f a
ys = sequenceA' xs -- :: f [a]
in ???
I use let in the last function to clarify the types which are involved. After you fill in the ??? you can of course remove the let.

You can extract a from f a with pattern matching or evaluation, if f is not IO
import Control.Applicative
import System.IO
import Control.Monad.ST
-- with AndrewC sequenceA' definition
sequenceA' :: (Applicative f) => [f a] -> f [a]
sequenceA' [] = pure []
sequenceA' (c:cs) = (:) <$> c <*> sequenceA' cs
seqOfMaybes :: [Maybe a] -> [a]
seqOfMaybes listOfMb = case sequenceA' listOfMb of
Nothing -> []
Just list -> list
-- sequencing ST computations
compute :: a -> ST s a
compute x = return x
seqOfSTData :: [Int] -> [Int]
seqOfSTData vals = runST $ (sequenceA' (map compute vals) :: ST s [Int])
-- but you cannot escape the applicative f if f is IO
readAnInt :: IO Int
readAnInt = putStrLn "give me an Int>" >> hFlush stdout >> getLine >>= (return . read)
seqOfIO :: [IO a] -> IO [a]
seqOfIO listOfIO = sequenceA' listOfIO
main :: IO ()
main = do
print $ seqOfMaybes [Just 3, Just 4, Just 5]
print $ seqOfSTData [1,2,3]
seqOfIO [readAnInt, readAnInt] >>= print

Related

Looking for a Haskell function related to liftA2, but works like <|> from Alternative

Consider this liftA2 function:
liftA2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c
liftA2 f Nothing Nothing = Nothing
liftA2 f (Just x) Nothing = Nothing
liftA2 f Nothing (Just y) = Nothing
liftA2 f (Just x) (Just y) = f x y
This is equivalent to the real liftA2 function from Control.Applicative, but specialized for Maybe. (and also liftM2 from Control.Monad)
I'm looking for a cousin of that function, that works like this:
mystery :: (a -> a -> a) -> Maybe a -> Maybe b -> Maybe c
mystery f Nothing Nothing = Nothing
mystery f (Just x) Nothing = Just x
mystery f Nothing (Just y) = Just y
mystery f (Just x) (Just y) = Just (f x y)
The closest concept I'm aware of is <|>, but that discards the second value if there are two, whereas I would rather pass a function to combine them.
What is this mystery function called? What type class does it operate on? What terms can I google to learn more? Thank you!
If you are willing to accept a different type signature, working with a Semigroup instance instead of with an arbitrary function f, then what you are looking for is the Option newtype from Data.Semigroup:
Prelude Data.Semigroup> Option Nothing <> Option Nothing
Option {getOption = Nothing}
Prelude Data.Semigroup> Option (Just [1]) <> Option Nothing
Option {getOption = Just [1]}
Prelude Data.Semigroup> Option Nothing <> Option (Just [2])
Option {getOption = Just [2]}
Prelude Data.Semigroup> Option (Just [1]) <> Option (Just [2])
Option {getOption = Just [1,2]}
For an arbitrary function you need something that is pretty specialized to Maybe - I don't really see how it could work for an arbitrary Applicative, or Alternative.
If I understand you correctly, you may be interested in the Semialign class from Data.Align, which offers zip-like operations that don't drop missing elements:
class Functor f => Semialign f where
align :: f a -> f b -> f (These a b)
align = alignWith id
alignWith :: (These a b -> c) -> f a -> f b -> f c
alignWith f as bs = f <$> align as bs
You can write
alignBasic :: Semialign f => (a -> a -> a) -> f a -> f a -> f a
alignBasic f = alignWith $ \case
This a -> a
That a -> a
These a1 a2 -> f a1 a2
-- or just
alignBasic f = alignWith (mergeThese f)
Since Maybe is an instance of Semialign, alignBasic can be used at type
alignBasic :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
Here goes an extra argument in support of alignWith being the liftA2 analogue you are looking for, as dfeuer suggests.
Using the monoidal presentation of Applicative...
fzip :: Applicative f => f a -> f b -> f (a, b)
fzip u v = (,) <$> u <*> v -- Think of this as a default implementation.
... we can do a subtle tweak on liftA2:
liftA2' :: Applicative f => ((a, b) -> c) -> f a -> f b -> f c
liftA2' f u v = f <$> fzip u v
This variation is relevant here because it translates straightforwardly to Alternative, under the products-to-sums monoidal functor interpretation:
-- fzip analogue. Name borrowed from protolude.
eitherA :: Alternative f => f a -> f b -> f (Either a b)
eitherA u v = (Left <$> u) <|> (Right <$> v)
-- Made-up name.
plusWith :: Alternative f => (Either a b -> c) -> f a -> f b -> f c
plusWith f u v = f <$> eitherA u v
plusWith, however, isn't helpful in your case. An Either a b -> c can't produce a c by combining an a with a b, except by discarding one of them. You'd rather have something that takes a These a b -> c argument, as using These a b can express the both-a-and-b case. It happens that a plusWith that uses These instead of Either is very much like alignWith:
-- Taken from the class definitions:
class Functor f => Semialign f where
align :: f a -> f b -> f (These a b)
align = alignWith id
alignWith :: (These a b -> c) -> f a -> f b -> f c
alignWith f a b = f <$> align a b
class Semialign f => Align f where
nil :: f a
Alternative is a class for monoidal functors from Hask-with-(,) to Hask-with-Either. Similarly, Align is a class for monoidal functors from Hask-with-(,) to Hask-with-These, only it also has extra idempotency and commutativity laws that ensure the unbiased behaviour you are looking for.
One aspect of Align worth noting is that it is closer to Alternative than to Applicative. In particular, the identity of the These tensor product is Void rather than (), and accordingly nil, the identity of align, is an empty structure rather than a singleton. That might come as a surprise, given that align and friends offer us greedy zips and zips with padding, and that zip is often thought of as an applicative operation. In this context, I feel it might help to mention a fact about ZipList. ZipList offers a zippy Applicative instance for lists in lieu of the default, cartesian product one:
GHCi> fzip [1,2] [3,9,27]
[(1,3),(1,9),(1,27),(2,3),(2,9),(2,27)]
GHCi> getZipList $ fzip (ZipList [1,2]) (ZipList [3,9,27])
[(1,3),(2,9)]
What is less widely known is that ZipList also has a different Alternative instance:
GHCi> [1,2] <|> [3,9,27]
[1,2,3,9,27]
GHCi> [3,9,27] <|> [1,2]
[3,9,27,1,2]
GHCi> getZipList $ ZipList [1,2] <|> ZipList [3,9,27]
[1,2,27]
GHCi> getZipList $ ZipList [3,9,27] <|> ZipList [1,2]
[3,9,27]
Instead of concatenating the lists, it pads the first list with a suffix of the second one to the larger of the two lengths. (It is a fitting instance for the type because it follows the left distribution law .) align for lists is somewhat similar to (<|>) #ZipList, except that it isn't biased towards either list:
GHCi> align [1,2] [3,9,27]
[These 1 3,These 2 9,That 27]
GHCi> align [3,9,27] [1,2]
[These 3 1,These 9 2,This 27]

Why the type of (pure [] 3) is "[a]"?

When I checked on ghci, I found this behavior;
Prelude> :t pure []
pure [] :: Applicative f => f [a]
Prelude> :t pure [] 3
pure [] 3 :: [a]
Prelude> pure [] 3
[]
I am not sure why it is like this, why pure [] 3 is type of [a]?
What happens in the last expression?
Short answer: It uses (->) b as f here.
The type of pure [] is pure [] :: Applicative f => f [a] as you first derived. Now you are calling that as a function. So that means that Haskell infers that f ~ Num b => (->) b with b the type of the 3. We are lucky here, since (->) b is indeed an instance of Applicative, it is defined as [src]:
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
liftA2 q f g x = q (f x) (g x)
So here the pure is interpreted as const :: a -> b -> a. We thus have written:
pure [] 3
-> const [] 3
-> (\_ -> []) 3
-> []
const thus ignores the 3 here, and thus the return type is a [] where the list can contain items of any type.

Idiomatic way to implement "m (t a) -> (a -> m (t b)) -> m (t b)" [duplicate]

This question already has answers here:
How to use bind with nested monads?
(2 answers)
Closed 5 years ago.
The bind function (>>=) has the signature:
m a -> (a -> m b) -> m b
However, I want a function with the signature:
m (t a) -> (a -> m (t b)) -> m (t b)
Specifically, I have a function that given an Integer, it returns a list of integers in within an IO:
f :: Int -> IO [Int]
but I want to apply it to an IO of list of Integers and I can't use the regular bind function because it is wrapped in two containers i.e. a list contained in an IO. Searching on hoogle doesn't help.
I am using the following approach to implement this:
Let's say the implementation of the function is:
f :: Int -> IO [Int]
f x = do
return $ [x-10, x+10]
I am using two helper functions to get what I want:
f' :: [Int] -> IO [Int]
f' xs = do
list <- traverse f xs
return $ join list
f'' :: IO [Int] -> IO [Int]
f'' xs = do
ys <- xs
f' ys
The above works but I would like to know if there is a better / idiomatic way to implement this in haskell?
The idiomatic solution would be to use Data.Functor.Compose:
data Compose f g a = Compose { getCompose :: f (g a) }
Since the function you're looking for is trivial to implement when Compose f g is a monad:
bibind :: Monad (Compose f g) => f (g a) -> (a -> f (g b)) -> f (g b)
bibind m h = getCompose (Compose m >>= Compose . h)
As well explained in this answer, it's not sufficient
for f and g to be Monads, they also need to commute:
class Commute f g where
commute :: g (f x) -> f (g x)
instance (Monad f, Monad g, Commute f g) => Monad (Compose f g) where
return = Compose . return . return
join = Compose . fmap join . join . fmap commute . getCompose . fmap getCompose
(In general, it's not sufficient for f to be a monad and g to be Traversable)

How can I implement generalized "zipn" and "unzipn" in Haskell?

I find this documentation in the basic Haskell libraries:
zip :: [a] -> [b] -> [(a, b)]
zip takes two lists and returns a list of corresponding pairs. If one input list is short, excess elements of the longer list are discarded.
zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
zip3 takes three lists and returns a list of triples, analogous to zip.
zip4 :: [a] -> [b] -> [c] -> [d] -> [(a, b, c, d)]
The zip4 function takes four lists and returns a list of quadruples, analogous to zip.
[...snip...]
unzip :: [(a, b)] -> ([a], [b])
unzip transforms a list of pairs into a list of first components and a list of second components.
unzip3 :: [(a, b, c)] -> ([a], [b], [c])
The unzip3 function takes a list of triples and returns three lists, analogous to unzip.
unzip4 :: [(a, b, c, d)] -> ([a], [b], [c], [d])
The unzip4 function takes a list of quadruples and returns four lists, analogous to unzip.
... and so on, up to zip7 and unzip7.
Is this a fundamental limitation of Haskell's type system? Or is there a way to implement zip and unzip once, to work on different configurations of input?
This is one very useful aspect of applicatives. Check out ZipList which is just a newtype wrapper around a simple list. The reason for the wrapper is that ZipList has an applicative instance for, you guessed it, zipping lists together. Then, if you want zip7 as bs cs ds es fs gs hs, you can just do something like
(,,,,,,) <$> as <*> bs <*> cs <*> ds <*> es <*> fs <*> gs <*> hs
As you can tell, this mechanism is meant to be also for extending zipWith, which is a general case of zip. To be honest, I think we should rip out all of the zipN functions and teach people the above instead. zip itself is fine, but beyond that...
Template Haskell solution
As the comments and other answers indicate, this is not a particularly satisfying answer. The one thing I was expecting someone else to implement was a TemplateHaskell version of zip and unzip. As no one has done so yet, here it is.
All it does is mechanically produce AST for zip or unzip functions. The idea behind zip is to use ZipList and behind unzip is to use foldr:
zip as ... zs === \as ... zs -> getZipList $ (, ... ,) <$> ZipList as <*> ... <*> ZipList zs
unzip === foldr (\ (a, ... ,z) ~(as, ... ,zs) -> (a:as, ... ,z:zs) ) ([], ... ,[])
The implementation looks like this.
{-# LANGUAGE TemplateHaskell #-}
module Zip (zip, unzip) where
import Prelude hiding (zip, unzip)
import Language.Haskell.TH
import Control.Monad
import Control.Applicative (ZipList(..))
-- | Given number, produces the `zip` function of corresponding arity
zip :: Int -> Q Exp
zip n = do
lists <- replicateM n (newName "xs")
lamE (varP <$> lists)
[| getZipList $
$(foldl (\a b -> [| $a <*> ZipList $(varE b) |])
[| pure $(conE (tupleDataName n)) |]
lists) |]
-- | Given number, produces the `unzip` function of corresponding arity
unzip :: Int -> Q Exp
unzip n = do
heads <- replicateM n (newName "x")
tails <- replicateM n (newName "xs")
[| foldr (\ $(tupP (varP <$> heads)) ~ $(tupP (varP <$> tails)) ->
$(tupE (zipWith (\x xs -> [| $x : $xs |])
(varE <$> heads)
(varE <$> tails))))
$(tupE (replicate n [| [] |])) |]
You can try this at GHCi:
ghci> :set -XTemplateHaskell
ghci> $(zip 3) [1..10] "abcd" [4,6..]
[(1,'a',4),(2,'b',6),(3,'c',8),(4,'d',10)]
ghci> $(unzip 3) [(1,'a',4),(2,'b',6),(3,'c',8),(4,'d',10)]
([1,2,3,4],"abcd",[4,6,8,10])
This is a zipN function that depends on the machinery of the generics-sop package:
{-# language TypeFamilies #-}
{-# language DataKinds #-}
{-# language TypeApplications #-}
import Control.Applicative
import Generics.SOP
-- "a" is some single-constructor product type, like some form of n-ary tuple
-- "xs" is a type-level list of the types of the elements of "a"
zipN :: (Generic a, Code a ~ '[ xs ]) => NP [] xs -> [a]
zipN np = to . SOP . Z <$> getZipList (hsequence (hliftA ZipList np))
main :: IO ()
main = do
let zipped = zipN #(_,_,_) ([1,2,3,4,5,6] :* ['a','b','c'] :* [True,False] :* Nil)
print $ zipped
The result:
[(1,'a',True),(2,'b',False)]
This solution has two disadvantages:
You have to wrap the argument lists in the special NP type from generics-sop that is constructed with :* and Nil.
You need to specify somehow that the result value is a list of tuples, and not a list of some other Generic-compatible type. Here, it is done with the #(_,_,_) type application.
2-ary, 3-ary.. n-ary tuples are all distinct data types, so you can't handle them uniformly directly, but you can introduce a type class that provides an interface that allows to define generic zip and unzip. Here is how it looks for generic unzip:
class Tuple t where
type Map (f :: * -> *) t
nilMap :: Proxy t -> (forall a. f a) -> Map f t
consMap :: (forall a. a -> f a -> f a) -> t -> Map f t -> Map f t
Map maps all types in a tuple type with f. nilMap constructs a Mapped tuple that contains empty values (I have no idea why Haskell requires that Proxy t there). consMap receives a function, a tuple and a Mapped tuple and zip the tuples with the function pointwise. Here is how instances look for 2- and 3-tuples:
instance Tuple (a, b) where
type Map f (a, b) = (f a, f b)
nilMap _ a = (a, a)
consMap f (x, y) (a, b) = (f x a, f y b)
instance Tuple (a, b, c) where
type Map f (a, b, c) = (f a, f b, f c)
nilMap _ a = (a, a, a)
consMap f (x, y, z) (a, b, c) = (f x a, f y b, f z c)
The gunzip itself:
gunzip :: forall t. Tuple t => [t] -> Map [] t
gunzip [] = nilMap (Proxy :: Proxy t) []
gunzip (p:ps) = consMap (:) p (gunzip ps)
This looks a lot like transpose:
transpose :: [[a]] -> [[a]]
transpose [] = repeat [] -- `gunzip` handles this case better
transpose (xs:xss) = zipWith (:) xs (transpose xss)
which it basically is, except with tuples. gunzip can be equivalently defined in terms of foldr as follows:
gunzip :: forall t. Tuple t => [t] -> Map [] t
gunzip = foldr (consMap (:)) $ nilMap (Proxy :: Proxy t) []
To define generic zip we need a type class of splittable data types (is there something like this on Hackage?).
class Splittable f g where
split :: f a -> g a (f a)
E.g. for lists we have
newtype MaybeBoth a b = MaybeBoth { getMaybeBoth :: Maybe (a, b) }
instance Splittable [] MaybeBoth where
split [] = MaybeBoth Nothing
split (x:xs) = MaybeBoth (Just (x, xs))
And here is what we add to the Tuple type class:
splitMap :: (Biapplicative g, Splittable f g) => Proxy (f t) -> Map f t -> g t (Map f t)
The Biapplicative g constraint ensures that it's possible to combine g a b and g c d into g (a, c) (b, d). For 2- and 3- tuples it looks like this:
splitMap _ (a, b) = biliftA2 (,) (,) (split a) (split b)
splitMap _ (a, b, c) = biliftA3 (,,) (,,) (split a) (split b) (split c)
After providing a Biapplicative instance for MaybeBoth
instance Biapplicative MaybeBoth where
bipure x y = MaybeBoth $ Just (x, y)
MaybeBoth f <<*>> MaybeBoth a = MaybeBoth $ uncurry (***) <$> f <*> a
we can finally define gzip:
gzip :: forall t. Tuple t => Map [] t -> [t]
gzip a = maybe [] (\(p, a') -> p : gzip a') . getMaybeBoth $ splitMap (Proxy :: Proxy [t]) a
It repeteadly cuts first elements of lists in a tuple, forms a tuple from them and prepends it to the result.
It should be possible to generalize gunzip by adding a dual to Splittable (Uniteable or something like that), but I'll stop here.
EDIT: I couldn't stop.
You are right that these functions (zip2, zip3 etc.) are all instances of the same pattern and in an ideal world, they should be implementable generically. By the way, as an exercise to the reader, figure out what zip1 and zip0 should be ;).
However, it is hard to implement zipN generically, because the common pattern between all the different cases is rather non-trivial. This does not mean it's impossible to implement it generically, but you'll need some of the more advanced type system features of Haskell GHC to do it.
To be more concrete, zip2, zip3 etc. all have a different number of arguments, making this an instance of "arity-generic programming" (the arity of a function is its number of arguments). As you might expect in the world of functional programming, there is an interesting research paper that covers precisely this topic ("arity-generic programming"), and conveniently, one of their main examples is... zipWithN. It doesn't directly answer your question because it uses Agda rather than Haskell, but you might still find it interesting. In any case, similar ideas can be implemented in terms of one or more of Haskell's GHC's more advanced type-system features (TypeFamilies and DataKinds come to mind). PDF version here.
By the way, this is just about an arity-generic zipWithN. For an arity-generic zipN, you probably need some support from the compiler, particularly an arity-generic interface to the tuple constructor, which I suspect might not be in GHC. This is what I believe augustss's comment to the question and chepner's comment to Alec's answer refer to.

How to map over Applicative form?

I want to map over Applicative form.
The type of map-like function would be like below:
mapX :: (Applicative f) => (f a -> f b) -> f [a] -> f [b]
used as:
result :: (Applicative f) => f [b]
result = mapX f xs
where f :: f a -> f b
f = ...
xs :: f[a]
xs = ...
As the background of this post, I try to write fluid simulation program using Applicative style referring to Paul Haduk's "The Haskell School of Expression", and I want to express the simulation with Applicative style as below:
x, v, a :: Sim VArray
x = x0 +: integral (v * dt)
v = v0 +: integral (a * dt)
a = (...calculate acceleration with x v...)
instance Applicative Sim where
...
where Sim type means the process of simulation computation and VArray means Array of Vector (x,y,z). X, v a are the arrays of position, velocity and acceleration, respectively.
Mapping over Applicative form comes when definining a.
I've found one answer to my question.
After all, my question is "How to lift high-order functions (like map
:: (a -> b) -> [a] -> [b]) to the Applicative world?" and the answer
I've found is "To build them using lifted first-order functions."
For example, the "mapX" is defined with lifted first-order functions
(headA, tailA, consA, nullA, condA) as below:
mapX :: (f a -> f b) -> f [a] -> f [b]
mapX f xs0 = condA (nullA xs0) (pure []) (consA (f x) (mapA f xs))
where
x = headA xs0
xs = tailA xs0
headA = liftA head
tailA = liftA tail
consA = liftA2 (:)
nullA = liftA null
condA b t e = liftA3 aux b t e
where aux b t e = if b then t else e
First, I don't think your proposed type signature makes much sense. Given an applicative list f [a] there's no general way to turn that into [f a] -- so there's no need for a function of type f a -> f b. For the sake of sanity, we'll reduce that function to a -> f b (to transform that into the other is trivial, but only if f is a monad).
So now we want:
mapX :: (Applicative f) => (a -> f b) -> f [a] -> f [b]
What immediately comes to mind now is traverse which is a generalization of mapM. Traverse, specialized to lists:
traverse :: (Applicative f) => (a -> f b) -> [a] -> f [b]
Close, but no cigar. Again, we can lift traverse to the required type signature, but this requires a monad constraint: mapX f xs = xs >>= traverse f.
If you don't mind the monad constraint, this is fine (and in fact you can do it more straightforwardly just with mapM). If you need to restrict yourself to applicative, then this should be enough to illustrate why you proposed signature isn't really possible.
Edit: based on further information, here's how I'd start to tackle the underlying problem.
-- your sketch
a = liftA sum $ mapX aux $ liftA2 neighbors (x!i) nbr
where aux :: f Int -> f Vector3
-- the type of "liftA2 neighbors (x!i) nbr" is "f [Int]
-- my interpretation
a = liftA2 aux x v
where
aux :: VArray -> VArray -> VArray
aux xi vi = ...
If you can't write aux like that -- as a pure function from the positions and velocities at one point in time to the accelerations, then you have bigger problems...
Here's an intuitive sketch as to why. The stream applicative functor takes a value and lifts it into a value over time -- a sequence or stream of values. If you have access to a value over time, you can derive properties of it. So velocity can be defined in terms of acceleration, position can be defined in terms of velocity, and soforth. Great! But now you want to define acceleration in terms of position and velocity. Also great! But you should not need, in this instance, to define acceleration in terms of velocity over time. Why, you may ask? Because velocity over time is all acceleration is to begin with. So if you define a in terms of dv, and v in terms of integral(a) then you've got a closed loop, and your equations are not propertly determined -- either there are, even given initial conditions, infinitely many solutions, or there are no solutions at all.
If I'm thinking about this right, you can't do this just with an applicative functor; you'll need a monad. If you have an Applicative—call it f—you have the following three functions available to you:
fmap :: (a -> b) -> f a -> f b
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
So, given some f :: f a -> f b, what can you do with it? Well, if you have some xs :: [a], then you can map it across: map (f . pure) xs :: [f b]. And if you instead have fxs :: f [a], then you could instead do fmap (map (f . pure)) fxs :: f [f b].1 However, you're stuck at this point. You want some function of type [f b] -> f [b], and possibly a function of type f (f b) -> f b; however, you can't define these on applicative functors (edit: actually, you can define the former; see the edit). Why? Well, if you look at fmap, pure, and <*>, you'll see that you have no way to get rid of (or rearrange) the f type constructor, so once you have [f a], you're stuck in that form.
Luckily, this is what monads are for: computations which can "change shape", so to speak. If you have a monad m, then in addition to the above, you get two extra methods (and return as a synonym for pure):
(>>=) :: m a -> (a -> m b) -> m b
join :: m (m a) -> m a
While join is only defined in Control.Monad, it's just as fundamental as >>=, and can sometimes be clearer to think about. Now we have the ability to define your [m b] -> m [b] function, or your m (m b) -> m b. The latter one is just join; and the former is sequence, from the Prelude. So, with monad m, you can define your mapX as
mapX :: Monad m => (m a -> m b) -> m [a] -> m [b]
mapX f mxs = mxs >>= sequence . map (f . return)
However, this would be an odd way to define it. There are a couple of other useful functions on monads in the prelude: mapM :: Monad m => (a -> m b) -> [a] -> m [b], which is equivalent to mapM f = sequence . map f; and (=<<) :: (a -> m b) -> m a -> m b, which is equivalent to flip (>>=). Using those, I'd probably define mapX as
mapX :: Monad m => (m a -> m b) -> m [a] -> m [b]
mapX f mxs = mapM (f . return) =<< mxs
Edit: Actually, my mistake: as John L kindly pointed out in a comment, Data.Traversable (which is a base package) supplies the function sequenceA :: (Applicative f, Traversable t) => t (f a) => f (t a); and since [] is an instance of Traversable, you can sequence an applicative functor. Nevertheless, your type signature still requires join or =<<, so you're still stuck. I would probably suggest rethinking your design; I think sclv probably has the right idea.
1: Or map (f . pure) <$> fxs, using the <$> synonym for fmap from Control.Applicative.
Here is a session in ghci where I define mapX the way you wanted it.
Prelude>
Prelude> import Control.Applicative
Prelude Control.Applicative> :t pure
pure :: Applicative f => a -> f a
Prelude Control.Applicative> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Prelude Control.Applicative> let mapX fun ma = pure fun <*> ma
Prelude Control.Applicative> :t mapX
mapX :: Applicative f => (a -> b) -> f a -> f b
I must however add that fmap is better to use, since Functor is less expressive than Applicative (that means that using fmap will work more often).
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
edit:
Oh, you have some other signature for mapX, anyway, you maybe meant the one I suggested (fmap)?

Resources