2015-04-22 22 views
6

Tôi mới dùng elm và lập trình chức năng nói chung. Nhưng tôi đang sử dụng elm và tôi thực sự cần một chức năng có một tín hiệu (List String) như là một đầu vào và trả về List (Signal String).Chức năng Elm với loại: Tín hiệu (Danh sách a) -> Danh sách (Tín hiệu a)

Tôi biết tôi có lẽ không nên có vấn đề này với thiết kế kiến ​​trúc tốt hơn trong chương trình của tôi nhưng có một chức năng có thể làm điều này sẽ giải quyết được một vấn đề lớn đối với tôi.

Các kết hợp chức năng không hoàn toàn ngược lại:

combine : List (Signal a) -> Signal (List a) 
combine = List.foldr (map2 (::)) (constant []) 

Tôi đã cố gắng để làm một cái gì đó tương tự như kết hợp chức năng nhưng đã không thành công cho đến nay. Bất kỳ ý tưởng về cách tạo ra chức năng như vậy?

Trả lời

4

này là không thể nói chung

Nghịch đảo của combine là không (nói chung) có thể.
Khi bạn có danh sách kích thước tĩnh của tín hiệu, bạn có thể combine chúng thành tín hiệu danh sách kích thước tĩnh. Nhưng khi bạn đi theo cách khác, không có gì đảm bảo rằng các danh sách trong tín hiệu là một kích thước tĩnh. Do đó bạn không thể "chỉ" xây dựng một danh sách ra khỏi nó.
(Nếu bạn có thể sau đó một giá trị bình thường của loại List có thể có kích thước thay đổi mà không hiển thị Signal xung quanh các loại, và bạn sẽ được tạo ra tự động và phá hủy tín hiệu trong danh sách. Đó là hai điều Elm không cho phép.)

Nhưng với một số hạn chế ...

Tất nhiên nếu bạn biết rằng danh sách trong tín hiệu có kích thước tĩnh, bạn có thể viết một chức năng cụ thể dựa trên giả định đó; chức năng đó sau đó sẽ thất bại trong thời gian chạy nếu trường hợp xảy ra rằng giả định của bạn về danh sách kích thước tĩnh là sai.

unsafe : Maybe a -> a 
unsafeHead m = 
    case m of 
    Just a -> a 
    Nothing -> Debug.crash "unsafe: You're out of luck. The `Maybe` was not a `Just`. " 

uncombine : Int -> Signal (List a) -> List (Signal a) 
uncombine n sig = 
    if n == 0 
    then [] 
    else Signal.map (List.head >> unsafe) sig 
     :: uncombine (n-1) (Signal.map (List.tail >> unsafe) sig) 

(Tôi khá chắc chắn câu hỏi này đã được thảo luận trên danh sách elm-discuss gửi thư một lần, nhưng tôi không thể tìm thấy nó nữa)

+0

Cảm ơn bạn @Apanatshka cho câu trả lời của bạn. Tôi hiểu rằng danh sách cần phải có kích thước tĩnh, nhưng vì tôi bướng bỉnh tôi muốn tiếp tục cố gắng và thay đổi chức năng uncombine thành: 'uncombine: Tín hiệu (Danh sách) -> Danh sách (Tín hiệu a) uncombine sig = nếu (Signal.map isEmpty sig) thì [] khác Signal.map (List.head >> không an toàn) sig :: uncombine (n-1) (Signal.map (List.tail >> unsafe) sig) '. Nhưng tôi nhận được lỗi không khớp loại vì mệnh đề if muốn giá trị Bool nhưng nhận giá trị Signal Bool. Có một số giải pháp cho vấn đề này không? –

+0

Không, không có giải pháp thay thế. Những gì bạn đang cố gắng là không thể. – Apanatshka

Các vấn đề liên quan