haskell: reader-monad for dependency-injection
i get the basic functionality of the reader-monad from learnyouahaskell book and i've seen some advises here to make use of it for dependency-injection.
even there are some examples here on stackoverflow, i dont know how to use it for integration-testing.
my code is:
list :: Ctx -> [String] -> IO String
list ctx args = do
d <- eitherDecode <$> Uplink.get (token ctx) (endpointActivities ctx) :: IO (Either String Activities)
case d of
Left err -> return err
Right result -> return $ unlines . filterByPrefix (parsePrefix args) . extractNames $ activities result
uplink.hs
get :: String -> String -> IO B.ByteString
get token endpoint = do
req <- parseRequest endpoint
resp <- httpLBS $ withAuth token req
return $ getResponseBody resp
how can i mock the httpLBS - call for integration-testing with the reader-monad?
EDIT: !!!!
i almost have it now with the reader-monad. the only problem left is that i dont know how i can define that httpsLBS-function in my Ctx-data-type.
httpLBS-function-signature:
httpLBS :: MonadIO m => Request -> m (Response ByteString)
my Ctx data-type-definition:
data Ctx =
Ctx {
token :: String,
endpointActivities :: String,
endpointTimeTrackingStart :: String,
httpLBSFunc :: MonadIO m => Request -> m (Response ByteString)
} deriving (Show)
i always get the error: Not in scope: type variable ‘m’
how can i define that function in my Ctx-data-type with its constraints?
i promise, that i will post my solution afterwards, when this last problem is solved
haskell dependency-injection
add a comment |
i get the basic functionality of the reader-monad from learnyouahaskell book and i've seen some advises here to make use of it for dependency-injection.
even there are some examples here on stackoverflow, i dont know how to use it for integration-testing.
my code is:
list :: Ctx -> [String] -> IO String
list ctx args = do
d <- eitherDecode <$> Uplink.get (token ctx) (endpointActivities ctx) :: IO (Either String Activities)
case d of
Left err -> return err
Right result -> return $ unlines . filterByPrefix (parsePrefix args) . extractNames $ activities result
uplink.hs
get :: String -> String -> IO B.ByteString
get token endpoint = do
req <- parseRequest endpoint
resp <- httpLBS $ withAuth token req
return $ getResponseBody resp
how can i mock the httpLBS - call for integration-testing with the reader-monad?
EDIT: !!!!
i almost have it now with the reader-monad. the only problem left is that i dont know how i can define that httpsLBS-function in my Ctx-data-type.
httpLBS-function-signature:
httpLBS :: MonadIO m => Request -> m (Response ByteString)
my Ctx data-type-definition:
data Ctx =
Ctx {
token :: String,
endpointActivities :: String,
endpointTimeTrackingStart :: String,
httpLBSFunc :: MonadIO m => Request -> m (Response ByteString)
} deriving (Show)
i always get the error: Not in scope: type variable ‘m’
how can i define that function in my Ctx-data-type with its constraints?
i promise, that i will post my solution afterwards, when this last problem is solved
haskell dependency-injection
1
I'm not sure I know what dependency injection really is, but why not parameterizeget
by the http client function, like:get myHttpLBS token endpoint = do ...
.Reader
is an abstraction around argument passing. I don't tend to reach for it unless both of: 1) I already have a monad stack, and 2) I have multiple top-level functions that call each other, and in particular I'd like to pass some value through a function, i.e. there is some function that does nothing but pass an argument to some other function. Other folks probably feel differently
– jberryman
Nov 13 '18 at 16:09
In functional programming, you can't use dependency injection because it makes everything impure. Instead, you compose functions, keeping as many of them pure as possible.
– Mark Seemann
Nov 13 '18 at 17:02
Did you writeuplink.hs
? Don't hard-codehttpLBS
; make it a parameter.
– chepner
Nov 13 '18 at 17:03
add a comment |
i get the basic functionality of the reader-monad from learnyouahaskell book and i've seen some advises here to make use of it for dependency-injection.
even there are some examples here on stackoverflow, i dont know how to use it for integration-testing.
my code is:
list :: Ctx -> [String] -> IO String
list ctx args = do
d <- eitherDecode <$> Uplink.get (token ctx) (endpointActivities ctx) :: IO (Either String Activities)
case d of
Left err -> return err
Right result -> return $ unlines . filterByPrefix (parsePrefix args) . extractNames $ activities result
uplink.hs
get :: String -> String -> IO B.ByteString
get token endpoint = do
req <- parseRequest endpoint
resp <- httpLBS $ withAuth token req
return $ getResponseBody resp
how can i mock the httpLBS - call for integration-testing with the reader-monad?
EDIT: !!!!
i almost have it now with the reader-monad. the only problem left is that i dont know how i can define that httpsLBS-function in my Ctx-data-type.
httpLBS-function-signature:
httpLBS :: MonadIO m => Request -> m (Response ByteString)
my Ctx data-type-definition:
data Ctx =
Ctx {
token :: String,
endpointActivities :: String,
endpointTimeTrackingStart :: String,
httpLBSFunc :: MonadIO m => Request -> m (Response ByteString)
} deriving (Show)
i always get the error: Not in scope: type variable ‘m’
how can i define that function in my Ctx-data-type with its constraints?
i promise, that i will post my solution afterwards, when this last problem is solved
haskell dependency-injection
i get the basic functionality of the reader-monad from learnyouahaskell book and i've seen some advises here to make use of it for dependency-injection.
even there are some examples here on stackoverflow, i dont know how to use it for integration-testing.
my code is:
list :: Ctx -> [String] -> IO String
list ctx args = do
d <- eitherDecode <$> Uplink.get (token ctx) (endpointActivities ctx) :: IO (Either String Activities)
case d of
Left err -> return err
Right result -> return $ unlines . filterByPrefix (parsePrefix args) . extractNames $ activities result
uplink.hs
get :: String -> String -> IO B.ByteString
get token endpoint = do
req <- parseRequest endpoint
resp <- httpLBS $ withAuth token req
return $ getResponseBody resp
how can i mock the httpLBS - call for integration-testing with the reader-monad?
EDIT: !!!!
i almost have it now with the reader-monad. the only problem left is that i dont know how i can define that httpsLBS-function in my Ctx-data-type.
httpLBS-function-signature:
httpLBS :: MonadIO m => Request -> m (Response ByteString)
my Ctx data-type-definition:
data Ctx =
Ctx {
token :: String,
endpointActivities :: String,
endpointTimeTrackingStart :: String,
httpLBSFunc :: MonadIO m => Request -> m (Response ByteString)
} deriving (Show)
i always get the error: Not in scope: type variable ‘m’
how can i define that function in my Ctx-data-type with its constraints?
i promise, that i will post my solution afterwards, when this last problem is solved
haskell dependency-injection
haskell dependency-injection
edited Nov 14 '18 at 21:49
stefa ng
asked Nov 13 '18 at 15:38
stefa ngstefa ng
7416
7416
1
I'm not sure I know what dependency injection really is, but why not parameterizeget
by the http client function, like:get myHttpLBS token endpoint = do ...
.Reader
is an abstraction around argument passing. I don't tend to reach for it unless both of: 1) I already have a monad stack, and 2) I have multiple top-level functions that call each other, and in particular I'd like to pass some value through a function, i.e. there is some function that does nothing but pass an argument to some other function. Other folks probably feel differently
– jberryman
Nov 13 '18 at 16:09
In functional programming, you can't use dependency injection because it makes everything impure. Instead, you compose functions, keeping as many of them pure as possible.
– Mark Seemann
Nov 13 '18 at 17:02
Did you writeuplink.hs
? Don't hard-codehttpLBS
; make it a parameter.
– chepner
Nov 13 '18 at 17:03
add a comment |
1
I'm not sure I know what dependency injection really is, but why not parameterizeget
by the http client function, like:get myHttpLBS token endpoint = do ...
.Reader
is an abstraction around argument passing. I don't tend to reach for it unless both of: 1) I already have a monad stack, and 2) I have multiple top-level functions that call each other, and in particular I'd like to pass some value through a function, i.e. there is some function that does nothing but pass an argument to some other function. Other folks probably feel differently
– jberryman
Nov 13 '18 at 16:09
In functional programming, you can't use dependency injection because it makes everything impure. Instead, you compose functions, keeping as many of them pure as possible.
– Mark Seemann
Nov 13 '18 at 17:02
Did you writeuplink.hs
? Don't hard-codehttpLBS
; make it a parameter.
– chepner
Nov 13 '18 at 17:03
1
1
I'm not sure I know what dependency injection really is, but why not parameterize
get
by the http client function, like: get myHttpLBS token endpoint = do ...
. Reader
is an abstraction around argument passing. I don't tend to reach for it unless both of: 1) I already have a monad stack, and 2) I have multiple top-level functions that call each other, and in particular I'd like to pass some value through a function, i.e. there is some function that does nothing but pass an argument to some other function. Other folks probably feel differently– jberryman
Nov 13 '18 at 16:09
I'm not sure I know what dependency injection really is, but why not parameterize
get
by the http client function, like: get myHttpLBS token endpoint = do ...
. Reader
is an abstraction around argument passing. I don't tend to reach for it unless both of: 1) I already have a monad stack, and 2) I have multiple top-level functions that call each other, and in particular I'd like to pass some value through a function, i.e. there is some function that does nothing but pass an argument to some other function. Other folks probably feel differently– jberryman
Nov 13 '18 at 16:09
In functional programming, you can't use dependency injection because it makes everything impure. Instead, you compose functions, keeping as many of them pure as possible.
– Mark Seemann
Nov 13 '18 at 17:02
In functional programming, you can't use dependency injection because it makes everything impure. Instead, you compose functions, keeping as many of them pure as possible.
– Mark Seemann
Nov 13 '18 at 17:02
Did you write
uplink.hs
? Don't hard-code httpLBS
; make it a parameter.– chepner
Nov 13 '18 at 17:03
Did you write
uplink.hs
? Don't hard-code httpLBS
; make it a parameter.– chepner
Nov 13 '18 at 17:03
add a comment |
1 Answer
1
active
oldest
votes
In Haskell, dependency injection is just higher order programming + currying. You can write your code as the following.
-- where (? -> ?) is the type of httpLBS
get_ :: (? -> ?) -> String -> String -> IO B.ByteString
get_ httpFunc token endpoint = do
req <- parseRequest endpoint
resp <- httpFunc $ withAuth token req
return $ getResponseBody resp
getProduction = get_ httpLBS
getTest = get_ httpMock
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53284484%2fhaskell-reader-monad-for-dependency-injection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
In Haskell, dependency injection is just higher order programming + currying. You can write your code as the following.
-- where (? -> ?) is the type of httpLBS
get_ :: (? -> ?) -> String -> String -> IO B.ByteString
get_ httpFunc token endpoint = do
req <- parseRequest endpoint
resp <- httpFunc $ withAuth token req
return $ getResponseBody resp
getProduction = get_ httpLBS
getTest = get_ httpMock
add a comment |
In Haskell, dependency injection is just higher order programming + currying. You can write your code as the following.
-- where (? -> ?) is the type of httpLBS
get_ :: (? -> ?) -> String -> String -> IO B.ByteString
get_ httpFunc token endpoint = do
req <- parseRequest endpoint
resp <- httpFunc $ withAuth token req
return $ getResponseBody resp
getProduction = get_ httpLBS
getTest = get_ httpMock
add a comment |
In Haskell, dependency injection is just higher order programming + currying. You can write your code as the following.
-- where (? -> ?) is the type of httpLBS
get_ :: (? -> ?) -> String -> String -> IO B.ByteString
get_ httpFunc token endpoint = do
req <- parseRequest endpoint
resp <- httpFunc $ withAuth token req
return $ getResponseBody resp
getProduction = get_ httpLBS
getTest = get_ httpMock
In Haskell, dependency injection is just higher order programming + currying. You can write your code as the following.
-- where (? -> ?) is the type of httpLBS
get_ :: (? -> ?) -> String -> String -> IO B.ByteString
get_ httpFunc token endpoint = do
req <- parseRequest endpoint
resp <- httpFunc $ withAuth token req
return $ getResponseBody resp
getProduction = get_ httpLBS
getTest = get_ httpMock
answered Nov 13 '18 at 18:46
Izaak WeissIzaak Weiss
671510
671510
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53284484%2fhaskell-reader-monad-for-dependency-injection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I'm not sure I know what dependency injection really is, but why not parameterize
get
by the http client function, like:get myHttpLBS token endpoint = do ...
.Reader
is an abstraction around argument passing. I don't tend to reach for it unless both of: 1) I already have a monad stack, and 2) I have multiple top-level functions that call each other, and in particular I'd like to pass some value through a function, i.e. there is some function that does nothing but pass an argument to some other function. Other folks probably feel differently– jberryman
Nov 13 '18 at 16:09
In functional programming, you can't use dependency injection because it makes everything impure. Instead, you compose functions, keeping as many of them pure as possible.
– Mark Seemann
Nov 13 '18 at 17:02
Did you write
uplink.hs
? Don't hard-codehttpLBS
; make it a parameter.– chepner
Nov 13 '18 at 17:03