Haskell初学者我如何获得IO(IO字符串)

Haskell初学者我如何获得IO(IO字符串),haskell,types,module,io,c-strings,Haskell,Types,Module,Io,C Strings,所以我想学习一些哈斯克尔(枯燥的夜班制),我制定了一个程序,可以通过计算我在任何特定时期的班次来简化我的假期计划 import System.Environment import Data.List import Data.List.Split import Data.Time import Data.Time.Calendar.WeekDate (toWeekDate) -- merge xs and ys lists alternating value from each [ xs(0)

所以我想学习一些哈斯克尔(枯燥的夜班制),我制定了一个程序,可以通过计算我在任何特定时期的班次来简化我的假期计划

import System.Environment
import Data.List
import Data.List.Split
import Data.Time
import Data.Time.Calendar.WeekDate (toWeekDate)


-- merge xs and ys lists alternating value from each [ xs(0),ys(0),(xs(1),ys(1)..xs(n),ys(n) ]
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys     

-- get part of list from index 'start' to 'stop'
slice :: Int -> Int -> [a] -> [a]
slice start_from stop_at xs = fst $ splitAt (stop_at - start_from) (snd $ splitAt start_from xs)

timeFormat = "%d-%m-%Y"
timeFormatOut :: Day -> String
timeFormatOut = formatTime defaultTimeLocale "%d-%m-%Y" 
-- parses Strings to DateTime Day1
parseMyDate :: String -> Day
parseMyDate = parseTimeOrError True defaultTimeLocale timeFormat

-- 8 week shift rotation
shiftRotation = cycle ["NAT","NAT","NAT","NAT","NAT","NAT","NAT","-","-","-","-","-","-","-","DAG","DAG","DAG","DAG","-","AFT","AFT","-","-","DAG","DAG","DAG","-","-","DAG","DAG","DAG","-","DAG","DAG","DAG","DAG","DAG","-","DAG","DAG","-","-","AFT","AFT","AFT","AFT","AFT","-","-","DAG(r)","DAG(r)","DAG(r)","DAG(r)","DAG(r)","(r)","(r)"]

hs_findshift :: String -> String -> String -> IO String
hs_findshift anchor start end = do
    let dayZero = parseMyDate anchor
    let startDate = parseMyDate start
    let endDate = parseMyDate end
    let startPos = fromIntegral (diffDays startDate dayZero)
    let endPos = fromIntegral (diffDays endDate dayZero) + 1
    let period = slice startPos endPos shiftRotation
    let dates = map (timeFormatOut) [startDate..endDate]
    let listStr = (concat(intersperse "," (merge dates period)))
    putStrLn listStr
这很有效。现在我想我应该试着把它导出到一个C#app,这样我就可以制作一个漂亮的界面。我有点麻烦了。我补充说

module Shiftlib where

import Foreign.C.String
import Foreign.C.Types
到顶端。在导入的正下方,我添加了一个块,用于将输入和输出转换为C类型

foreign export ccall findshift :: CString -> CString -> CString -> IO CString

findshift :: CString -> CString -> CString -> IO CString
findshift a s e = do
    anchor <- peekCString a
    start <- peekCString s
    end <- peekCString e
    result <- hs_findshift anchor start end
    return $ newCString result
foreign export ccall findshift::CString->CString->CString->IO CString
findshift::CString->CString->CString->IO CString
findshift a s e=do
锚
当你已经拥有你想要的东西时,只需停止,
newCString result


当您在
IO
monad中使用类型为
foo::…->的函数时,只需在您已经拥有想要的东西时停止,
newCString result

IO T
do
块中的最后一个条目必须具有类型
IO T

return
存在,因此,如果您只有
T
,则可以将其包装在
IO
中。本质上,类型为
T
的表达式计算为类型为
T
的值,没有任何副作用(例如打印消息或变异
IORef
s)
return
将该值转换为类型为
iot
的IO计算。类型
IO T
用于返回
T
之前可能有副作用的表达式
return
创建一个没有副作用的计算,作为
iot
的一个小的子类

newCString结果
已经是
IO CString
类型,因此如果使用
return
会将其包装太多次,因为类型为
IO(IO CString)
。这是一个不返回字符串的计算,而是另一个要运行的计算(最终将生成字符串)

这里显而易见的解决方案是删除
返回
,以避免冗余包装

另一个不推荐的解决方案是

do ...
   ...
   string <- newCString result
   return string
这也会产生同样的效果。但这毫无意义,而且影响了可读性


你的代码是完美的,因为它是。也许你也想用“应用风格”来考虑一些备选方案。

findshift::CString->CString->CString->IO CString
findshift a s e=do
结果CString->CString->IO CString
findshift a s e=
hs_查找换档Peek Cstring a Peek Cstring s Peek Cstring e>>=新建Cstring

(不过,我不喜欢最后一个。)

当您在
IO
monad中使用类型为
foo::…->IO T
do
块中的最后一个条目必须具有类型
IO T

return
存在,因此,如果您只有
T
,则可以将其包装在
IO
中。本质上,类型为
T
的表达式计算为类型为
T
的值,没有任何副作用(例如打印消息或变异
IORef
s)
return
将该值转换为类型为
iot
的IO计算。类型
IO T
用于返回
T
之前可能有副作用的表达式
return
创建一个没有副作用的计算,作为
iot
的一个小的子类

newCString结果
已经是
IO CString
类型,因此如果使用
return
会将其包装太多次,因为类型为
IO(IO CString)
。这是一个不返回字符串的计算,而是另一个要运行的计算(最终将生成字符串)

这里显而易见的解决方案是删除
返回
,以避免冗余包装

另一个不推荐的解决方案是

do ...
   ...
   string <- newCString result
   return string
这也会产生同样的效果。但这毫无意义,而且影响了可读性


你的代码是完美的,因为它是。也许你也想用“应用风格”来考虑一些备选方案。

findshift::CString->CString->CString->IO CString
findshift a s e=do
结果CString->CString->IO CString
findshift a s e=
hs_查找换档Peek Cstring a Peek Cstring s Peek Cstring e>>=新建Cstring

(不过,我不喜欢最后一个。)。我懂了。因此,IO在返回时再次添加。我必须承认我有点认为IO只能被添加一次——要么是在IO域中,要么不是。一定是误解了。@JakobBrøgger,这样一来,
IO
就像其他类型的构造函数一样。就像你可以有一个字符串列表一样,你也可以有一个
IO
IO
string.Ahh。我懂了。因此,IO在返回时再次添加。我必须承认我有点认为IO只能被添加一次——要么是在IO域中,要么不是。一定是误解了。@JakobBrøgger,这样一来,
IO
就像其他类型的构造函数一样。就像你可以有一个字符串列表一样,你也可以有一个
IO
IO
字符串。
merge(x:xs)ys=x:merge ys-xs
更好。
merge(x:xs)ys=x:merge ys-xs
更好。
do ...
   ...
   string <- newCString result
   return string
do ...
   ...
   string <- newCString result
   string2 <- return string
   string3 <- return string2
   return string3
findshift :: CString -> CString -> CString -> IO CString
findshift a s e = do
    result <- hs_findshift <$> peekCString a <*> peekCString s <*> peekCString e
    newCString result
findshift :: CString -> CString -> CString -> IO CString
findshift a s e =
    hs_findshift <$> peekCString a <*> peekCString s <*> peekCString e >>= newCString